mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
drm: renesas: rz-du: mipi_dsi: Add OF data support
n preparation for adding support for the Renesas RZ/V2H(P) SoC, this patch introduces a mechanism to pass SoC-specific information via OF data in the DSI driver. This enables the driver to adapt dynamically to various SoC-specific requirements without hardcoding configurations. The MIPI DSI interface on the RZ/V2H(P) SoC is nearly identical to the one on the RZ/G2L SoC. While the LINK registers are shared between the two SoCs, the D-PHY registers differ. Also the VCLK range differs on both these SoCs. To accommodate these differences `struct rzg2l_mipi_dsi_hw_info` is introduced and as now passed as OF data. These changes lay the groundwork for the upcoming RZ/V2H(P) SoC support by allowing SoC-specific data to be passed through OF. Co-developed-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com> Signed-off-by: Fabrizio Castro <fabrizio.castro.jz@renesas.com> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> Reviewed-by: Biju Das <biju.das.jz@bp.renesas.com> Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> Link: https://lore.kernel.org/r/20250609225630.502888-5-prabhakar.mahadev-lad.rj@bp.renesas.com
This commit is contained in:
parent
3c55c4f05c
commit
2991c3f0ca
|
|
@ -34,10 +34,23 @@
|
|||
|
||||
#define RZG2L_DCS_BUF_SIZE 128 /* Maximum DCS buffer size in external memory. */
|
||||
|
||||
struct rzg2l_mipi_dsi;
|
||||
|
||||
struct rzg2l_mipi_dsi_hw_info {
|
||||
int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, unsigned long hsfreq);
|
||||
void (*dphy_exit)(struct rzg2l_mipi_dsi *dsi);
|
||||
u32 phy_reg_offset;
|
||||
u32 link_reg_offset;
|
||||
unsigned long min_dclk;
|
||||
unsigned long max_dclk;
|
||||
};
|
||||
|
||||
struct rzg2l_mipi_dsi {
|
||||
struct device *dev;
|
||||
void __iomem *mmio;
|
||||
|
||||
const struct rzg2l_mipi_dsi_hw_info *info;
|
||||
|
||||
struct reset_control *rstc;
|
||||
struct reset_control *arstc;
|
||||
struct reset_control *prstc;
|
||||
|
|
@ -174,22 +187,22 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
|
|||
|
||||
static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
|
||||
{
|
||||
iowrite32(data, dsi->mmio + reg);
|
||||
iowrite32(data, dsi->mmio + dsi->info->phy_reg_offset + reg);
|
||||
}
|
||||
|
||||
static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
|
||||
{
|
||||
iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
|
||||
iowrite32(data, dsi->mmio + dsi->info->link_reg_offset + reg);
|
||||
}
|
||||
|
||||
static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
|
||||
{
|
||||
return ioread32(dsi->mmio + reg);
|
||||
return ioread32(dsi->mmio + dsi->info->phy_reg_offset + reg);
|
||||
}
|
||||
|
||||
static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
|
||||
{
|
||||
return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
|
||||
return ioread32(dsi->mmio + dsi->info->link_reg_offset + reg);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
|
@ -305,7 +318,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
|
|||
bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
|
||||
hsfreq = DIV_ROUND_CLOSEST_ULL(vclk_rate * bpp, dsi->lanes);
|
||||
|
||||
ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
|
||||
ret = dsi->info->dphy_init(dsi, hsfreq);
|
||||
if (ret < 0)
|
||||
goto err_phy;
|
||||
|
||||
|
|
@ -357,7 +370,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
|
|||
return 0;
|
||||
|
||||
err_phy:
|
||||
rzg2l_mipi_dsi_dphy_exit(dsi);
|
||||
dsi->info->dphy_exit(dsi);
|
||||
pm_runtime_put(dsi->dev);
|
||||
|
||||
return ret;
|
||||
|
|
@ -365,7 +378,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
|
|||
|
||||
static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
|
||||
{
|
||||
rzg2l_mipi_dsi_dphy_exit(dsi);
|
||||
dsi->info->dphy_exit(dsi);
|
||||
pm_runtime_put(dsi->dev);
|
||||
}
|
||||
|
||||
|
|
@ -615,10 +628,12 @@ rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
|
|||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->clock > 148500)
|
||||
struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
|
||||
|
||||
if (mode->clock > dsi->info->max_dclk)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
if (mode->clock < 5803)
|
||||
if (mode->clock < dsi->info->min_dclk)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
return MODE_OK;
|
||||
|
|
@ -905,6 +920,8 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
|
|||
platform_set_drvdata(pdev, dsi);
|
||||
dsi->dev = &pdev->dev;
|
||||
|
||||
dsi->info = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dsi->dev, ret,
|
||||
|
|
@ -948,13 +965,13 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
|
|||
* mode->clock and format are not available. So initialize DPHY with
|
||||
* timing parameters for 80Mbps.
|
||||
*/
|
||||
ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000000);
|
||||
ret = dsi->info->dphy_init(dsi, 80000000);
|
||||
if (ret < 0)
|
||||
goto err_phy;
|
||||
|
||||
txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
|
||||
dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
|
||||
rzg2l_mipi_dsi_dphy_exit(dsi);
|
||||
dsi->info->dphy_exit(dsi);
|
||||
pm_runtime_put(dsi->dev);
|
||||
|
||||
/* Initialize the DRM bridge. */
|
||||
|
|
@ -975,7 +992,7 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_phy:
|
||||
rzg2l_mipi_dsi_dphy_exit(dsi);
|
||||
dsi->info->dphy_exit(dsi);
|
||||
pm_runtime_put(dsi->dev);
|
||||
err_pm_disable:
|
||||
pm_runtime_disable(dsi->dev);
|
||||
|
|
@ -992,8 +1009,16 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
static const struct rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = {
|
||||
.dphy_init = rzg2l_mipi_dsi_dphy_init,
|
||||
.dphy_exit = rzg2l_mipi_dsi_dphy_exit,
|
||||
.link_reg_offset = 0x10000,
|
||||
.min_dclk = 5803,
|
||||
.max_dclk = 148500,
|
||||
};
|
||||
|
||||
static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
|
||||
{ .compatible = "renesas,rzg2l-mipi-dsi" },
|
||||
{ .compatible = "renesas,rzg2l-mipi-dsi", .data = &rzg2l_mipi_dsi_info, },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@
|
|||
#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0)
|
||||
|
||||
/* --------------------------------------------------------*/
|
||||
/* Link Registers */
|
||||
#define LINK_REG_OFFSET 0x10000
|
||||
|
||||
/* Link Status Register */
|
||||
#define LINKSR 0x10
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user