Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions drivers/gpu/drm/bridge/cadence/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@ config DRM_CDNS_DSI
help
Support Cadence DPI to DSI bridge. This is an internal
bridge and is meant to be directly embedded in a SoC.

if DRM_CDNS_DSI

config DRM_CDNS_DSI_J721E
bool "J721E Cadence DPI/DSI wrapper support"
default y
help
Support J721E Cadence DPI/DSI wrapper. This wrapper adds
support to select which DPI input to use for the bridge.
endif
1 change: 1 addition & 0 deletions drivers/gpu/drm/bridge/cadence/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ cdns-mhdp8546-y := cdns-mhdp8546-core.o
cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
cdns-dsi-y := cdns-dsi-core.o
cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o
66 changes: 58 additions & 8 deletions drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>

#include "cdns-dsi-core.h"
#ifdef CONFIG_DRM_CDNS_DSI_J721E
#include "cdns-dsi-j721e.h"
#endif

static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
{
Expand Down Expand Up @@ -265,11 +269,19 @@ static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)

val = readl(dsi->regs + MCTL_MAIN_EN) & ~IF_EN(input->id);
writel(val, dsi->regs + MCTL_MAIN_EN);

if (dsi->platform_ops && dsi->platform_ops->disable)
dsi->platform_ops->disable(dsi);

pm_runtime_put(dsi->base.dev);
}

static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
{
return;
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);

pm_runtime_put(dsi->base.dev);
}

static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
Expand Down Expand Up @@ -353,6 +365,12 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
u32 tmp, reg_wakeup, div;
int nlanes;

if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
return;

if (dsi->platform_ops && dsi->platform_ops->enable)
dsi->platform_ops->enable(dsi);

mode = &bridge->encoder->crtc->state->adjusted_mode;
nlanes = output->dev->lanes;

Expand Down Expand Up @@ -480,6 +498,9 @@ static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
struct cdns_dsi *dsi = input_to_dsi(input);

if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
return;

cdns_dsi_init_link(dsi);
cdns_dsi_hs_init(dsi);
}
Expand Down Expand Up @@ -600,6 +621,10 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
struct mipi_dsi_packet packet;
int ret, i, tx_len, rx_len;

ret = pm_runtime_resume_and_get(host->dev);
if (ret < 0)
return ret;

cdns_dsi_init_link(dsi);

ret = mipi_dsi_create_packet(&packet, msg);
Expand Down Expand Up @@ -700,6 +725,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
}

out:
pm_runtime_put(host->dev);
return ret;
}

Expand Down Expand Up @@ -728,6 +754,7 @@ static int __maybe_unused cdns_dsi_suspend(struct device *dev)
clk_disable_unprepare(dsi->dsi_p_clk);
reset_control_assert(dsi->dsi_p_rst);
dsi->link_initialized = false;
dsi->phy_initialized = false;
return 0;
}

Expand Down Expand Up @@ -755,11 +782,6 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
if (IS_ERR(dsi->regs))
return PTR_ERR(dsi->regs);

res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dsi->wrap_regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dsi->regs))
return PTR_ERR(dsi->regs);

dsi->dsi_p_clk = devm_clk_get(&pdev->dev, "dsi_p_clk");
if (IS_ERR(dsi->dsi_p_clk))
return PTR_ERR(dsi->dsi_p_clk);
Expand Down Expand Up @@ -792,7 +814,7 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
goto err_disable_pclk;
}

writel(1, dsi->wrap_regs + 4);
dsi->platform_ops = of_device_get_match_data(&pdev->dev);

val = readl(dsi->regs + IP_CONF);
dsi->direct_cmd_fifo_depth = 1 << (DIRCMD_FIFO_DEPTH(val) + 2);
Expand Down Expand Up @@ -825,15 +847,34 @@ static int cdns_dsi_drm_probe(struct platform_device *pdev)
if (ret)
goto err_disable_pclk;

pm_runtime_enable(&pdev->dev);
dsi->base.dev = &pdev->dev;
dsi->base.ops = &cdns_dsi_ops;

if (dsi->platform_ops && dsi->platform_ops->init) {
ret = dsi->platform_ops->init(dsi);
if (ret != 0) {
dev_err(&pdev->dev, "platform initialization failed: %d\n",
ret);
goto err_disable_runtime_pm;
}
}

ret = mipi_dsi_host_register(&dsi->base);
if (ret)
goto err_deinit_platform;

clk_disable_unprepare(dsi->dsi_p_clk);

return 0;

err_deinit_platform:
if (dsi->platform_ops && dsi->platform_ops->exit)
dsi->platform_ops->exit(dsi);

err_disable_runtime_pm:
pm_runtime_disable(&pdev->dev);

err_disable_pclk:
clk_disable_unprepare(dsi->dsi_p_clk);

Expand All @@ -845,13 +886,22 @@ static int cdns_dsi_drm_remove(struct platform_device *pdev)
struct cdns_dsi *dsi = platform_get_drvdata(pdev);

mipi_dsi_host_unregister(&dsi->base);
//pm_runtime_disable(&pdev->dev);

if (dsi->platform_ops && dsi->platform_ops->exit)
dsi->platform_ops->exit(dsi);

pm_runtime_disable(&pdev->dev);

return 0;
}

static const struct of_device_id cdns_dsi_of_match[] = {
{ .compatible = "cdns,dsi" },
#ifdef CONFIG_DRM_CDNS_DSI_J721E
{ .compatible = "ti,j721e-dsi",
.data = &dsi_ti_j721e_ops,
},
#endif
{ },
};
MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
Expand Down
14 changes: 13 additions & 1 deletion drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,22 @@ struct cdns_dsi_input {
struct drm_bridge bridge;
};

struct cdns_dsi;

struct dsi_platform_ops {
int (*init)(struct cdns_dsi *dsi);
void (*exit)(struct cdns_dsi *dsi);
void (*enable)(struct cdns_dsi *dsi);
void (*disable)(struct cdns_dsi *dsi);
};

struct cdns_dsi {
struct mipi_dsi_host base;
void __iomem *regs;
void __iomem *wrap_regs;
#ifdef CONFIG_DRM_CDNS_DSI_J721E
void __iomem *j721e_regs;
#endif
const struct dsi_platform_ops *platform_ops;
struct cdns_dsi_input input;
struct cdns_dsi_output output;
unsigned int direct_cmd_fifo_depth;
Expand Down
51 changes: 51 additions & 0 deletions drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0
/*
* TI j721e Cadence DSI wrapper
*
* Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
* Author: Rahul T R <r-ravikumar@ti.com>
*/

#include <linux/io.h>
#include <linux/platform_device.h>

#include "cdns-dsi-j721e.h"

#define DSI_WRAP_REVISION 0x0
#define DSI_WRAP_DPI_CONTROL 0x4
#define DSI_WRAP_DSC_CONTROL 0x8
#define DSI_WRAP_DPI_SECURE 0xc
#define DSI_WRAP_DSI_0_ASF_STATUS 0x10

#define DSI_WRAP_DPI_0_EN BIT(0)
#define DSI_WRAP_DSI2_MUX_SEL BIT(4)

static int cdns_dsi_j721e_init(struct cdns_dsi *dsi)
{
struct platform_device *pdev = to_platform_device(dsi->base.dev);

dsi->j721e_regs = devm_platform_ioremap_resource(pdev, 1);
return PTR_ERR_OR_ZERO(dsi->j721e_regs);
}

static void cdns_dsi_j721e_enable(struct cdns_dsi *dsi)
{
/*
* Enable DPI0 as its input. DSS0 DPI2 is connected
* to DSI DPI0. This is the only supported configuration on
* J721E.
*/
writel(DSI_WRAP_DPI_0_EN, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL);
}

static void cdns_dsi_j721e_disable(struct cdns_dsi *dsi)
{
/* Put everything to defaults */
writel(0, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL);
}

const struct dsi_platform_ops dsi_ti_j721e_ops = {
.init = cdns_dsi_j721e_init,
.enable = cdns_dsi_j721e_enable,
.disable = cdns_dsi_j721e_disable,
};
18 changes: 18 additions & 0 deletions drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* TI j721e Cadence DSI wrapper
*
* Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
* Author: Rahul T R <r-ravikumar@ti.com>
*/

#ifndef CDNS_DSI_J721E_H
#define CDNS_DSI_J721E_H

#include "cdns-dsi-core.h"

struct dsi_platform_ops;

extern const struct dsi_platform_ops dsi_ti_j721e_ops;

#endif /* !CDNS_DSI_J721E_H */
Loading