Commit 46f28427 authored by Daniel Vetter's avatar Daniel Vetter

Merge tag 'drm-rcar-next-20230325' of...

Merge tag 'drm-rcar-next-20230325' of git://git.kernel.org/pub/scm/linux/kernel/git/pinchartl/linux into drm-next

Miscellaneous fixes and improvements for rcar-du
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230325204922.GD19335@pendragon.ideasonboard.com
parents 7ed34927 40f43730
...@@ -298,13 +298,26 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) ...@@ -298,13 +298,26 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
escr = params.escr; escr = params.escr;
} }
if (rcdu->info->gen < 4) { /*
* The ESCR register only exists in DU channels that can output to an
* LVDS or DPAT, and the OTAR register in DU channels that can output
* to a DPAD.
*/
if ((rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs |
rcdu->info->routes[RCAR_DU_OUTPUT_DPAD1].possible_crtcs |
rcdu->info->routes[RCAR_DU_OUTPUT_LVDS0].possible_crtcs |
rcdu->info->routes[RCAR_DU_OUTPUT_LVDS1].possible_crtcs) &
BIT(rcrtc->index)) {
dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr); dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr); rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
} }
if ((rcdu->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs |
rcdu->info->routes[RCAR_DU_OUTPUT_DPAD1].possible_crtcs) &
BIT(rcrtc->index))
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
/* Signal polarities */ /* Signal polarities */
dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0) dsmr = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0) | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
...@@ -749,16 +762,17 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -749,16 +762,17 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
/* /*
* On D3/E3 the dot clock is provided by the LVDS encoder attached to * On D3/E3 the dot clock is provided by the LVDS encoder attached to
* the DU channel. We need to enable its clock output explicitly if * the DU channel. We need to enable its clock output explicitly before
* the LVDS output is disabled. * starting the CRTC, as the bridge hasn't been enabled by the atomic
* helpers yet.
*/ */
if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) && if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) { bool dot_clk_only = rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0);
struct drm_bridge *bridge = rcdu->lvds[rcrtc->index]; struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
const struct drm_display_mode *mode = const struct drm_display_mode *mode =
&crtc->state->adjusted_mode; &crtc->state->adjusted_mode;
rcar_lvds_pclk_enable(bridge, mode->clock * 1000); rcar_lvds_pclk_enable(bridge, mode->clock * 1000, dot_clk_only);
} }
/* /*
...@@ -795,15 +809,16 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, ...@@ -795,15 +809,16 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
rcar_du_crtc_stop(rcrtc); rcar_du_crtc_stop(rcrtc);
rcar_du_crtc_put(rcrtc); rcar_du_crtc_put(rcrtc);
if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index) && if (rcdu->info->lvds_clk_mask & BIT(rcrtc->index)) {
rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0)) { bool dot_clk_only = rstate->outputs == BIT(RCAR_DU_OUTPUT_DPAD0);
struct drm_bridge *bridge = rcdu->lvds[rcrtc->index]; struct drm_bridge *bridge = rcdu->lvds[rcrtc->index];
/* /*
* Disable the LVDS clock output, see * Disable the LVDS clock output, see
* rcar_du_crtc_atomic_enable(). * rcar_du_crtc_atomic_enable(). When the LVDS output is used,
* this also disables the LVDS encoder.
*/ */
rcar_lvds_pclk_disable(bridge); rcar_lvds_pclk_disable(bridge, dot_clk_only);
} }
if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) && if ((rcdu->info->dsi_clk_mask & BIT(rcrtc->index)) &&
...@@ -815,7 +830,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, ...@@ -815,7 +830,6 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
* Disable the DSI clock output, see * Disable the DSI clock output, see
* rcar_du_crtc_atomic_enable(). * rcar_du_crtc_atomic_enable().
*/ */
rcar_mipi_dsi_pclk_disable(bridge); rcar_mipi_dsi_pclk_disable(bridge);
} }
......
...@@ -109,8 +109,8 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, ...@@ -109,8 +109,8 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
renc = drmm_encoder_alloc(&rcdu->ddev, struct rcar_du_encoder, base, renc = drmm_encoder_alloc(&rcdu->ddev, struct rcar_du_encoder, base,
&rcar_du_encoder_funcs, DRM_MODE_ENCODER_NONE, &rcar_du_encoder_funcs, DRM_MODE_ENCODER_NONE,
NULL); NULL);
if (!renc) if (IS_ERR(renc))
return -ENOMEM; return PTR_ERR(renc);
renc->output = output; renc->output = output;
......
...@@ -138,6 +138,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) ...@@ -138,6 +138,7 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
{ {
struct rcar_du_device *rcdu = rgrp->dev; struct rcar_du_device *rcdu = rgrp->dev;
u32 defr7 = DEFR7_CODE; u32 defr7 = DEFR7_CODE;
u32 dorcr;
/* Enable extended features */ /* Enable extended features */
rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE); rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
...@@ -174,8 +175,15 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp) ...@@ -174,8 +175,15 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
/* /*
* Use DS1PR and DS2PR to configure planes priorities and connects the * Use DS1PR and DS2PR to configure planes priorities and connects the
* superposition 0 to DU0 pins. DU1 pins will be configured dynamically. * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
*
* Groups that have a single channel have a hardcoded configuration. On
* Gen3 and newer, the documentation requires PG1T, DK1S and PG1D_DS1 to
* always be set in this case.
*/ */
rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS); dorcr = DORCR_PG0D_DS0 | DORCR_DPRS;
if (rcdu->info->gen >= 3 && rgrp->num_crtcs == 1)
dorcr |= DORCR_PG1T | DORCR_DK1S | DORCR_PG1D_DS1;
rcar_du_group_write(rgrp, DORCR, dorcr);
/* Apply planes to CRTCs association. */ /* Apply planes to CRTCs association. */
mutex_lock(&rgrp->lock); mutex_lock(&rgrp->lock);
...@@ -349,7 +357,7 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp) ...@@ -349,7 +357,7 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
struct rcar_du_device *rcdu = rgrp->dev; struct rcar_du_device *rcdu = rgrp->dev;
u32 dorcr = rcar_du_group_read(rgrp, DORCR); u32 dorcr = rcar_du_group_read(rgrp, DORCR);
dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK); dorcr &= ~(DORCR_PG1T | DORCR_DK1S | DORCR_PG1D_MASK);
/* /*
* Set the DPAD1 pins sources. Select CRTC 0 if explicitly requested and * Set the DPAD1 pins sources. Select CRTC 0 if explicitly requested and
...@@ -357,9 +365,9 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp) ...@@ -357,9 +365,9 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
* by default. * by default.
*/ */
if (rcdu->dpad1_source == rgrp->index * 2) if (rcdu->dpad1_source == rgrp->index * 2)
dorcr |= DORCR_PG2D_DS1; dorcr |= DORCR_PG1D_DS0;
else else
dorcr |= DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_DS2; dorcr |= DORCR_PG1T | DORCR_DK1S | DORCR_PG1D_DS1;
rcar_du_group_write(rgrp, DORCR, dorcr); rcar_du_group_write(rgrp, DORCR, dorcr);
......
...@@ -511,19 +511,19 @@ ...@@ -511,19 +511,19 @@
*/ */
#define DORCR 0x11000 #define DORCR 0x11000
#define DORCR_PG2T (1 << 30) #define DORCR_PG1T (1 << 30)
#define DORCR_DK2S (1 << 28) #define DORCR_DK1S (1 << 28)
#define DORCR_PG2D_DS1 (0 << 24) #define DORCR_PG1D_DS0 (0 << 24)
#define DORCR_PG2D_DS2 (1 << 24) #define DORCR_PG1D_DS1 (1 << 24)
#define DORCR_PG2D_FIX0 (2 << 24) #define DORCR_PG1D_FIX0 (2 << 24)
#define DORCR_PG2D_DOOR (3 << 24) #define DORCR_PG1D_DOOR (3 << 24)
#define DORCR_PG2D_MASK (3 << 24) #define DORCR_PG1D_MASK (3 << 24)
#define DORCR_DR1D (1 << 21) #define DORCR_DR0D (1 << 21)
#define DORCR_PG1D_DS1 (0 << 16) #define DORCR_PG0D_DS0 (0 << 16)
#define DORCR_PG1D_DS2 (1 << 16) #define DORCR_PG0D_DS1 (1 << 16)
#define DORCR_PG1D_FIX0 (2 << 16) #define DORCR_PG0D_FIX0 (2 << 16)
#define DORCR_PG1D_DOOR (3 << 16) #define DORCR_PG0D_DOOR (3 << 16)
#define DORCR_PG1D_MASK (3 << 16) #define DORCR_PG0D_MASK (3 << 16)
#define DORCR_RGPV (1 << 4) #define DORCR_RGPV (1 << 4)
#define DORCR_DPRS (1 << 0) #define DORCR_DPRS (1 << 0)
......
...@@ -73,7 +73,7 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) ...@@ -73,7 +73,7 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
.src.y2 = mode->vdisplay << 16, .src.y2 = mode->vdisplay << 16,
.zpos = 0, .zpos = 0,
}, },
.format = rcar_du_format_info(DRM_FORMAT_ARGB8888), .format = rcar_du_format_info(DRM_FORMAT_XRGB8888),
.source = RCAR_DU_PLANE_VSPD1, .source = RCAR_DU_PLANE_VSPD1,
.colorkey = 0, .colorkey = 0,
}; };
......
...@@ -269,7 +269,7 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk, ...@@ -269,7 +269,7 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
pll->pll_m, pll->pll_n, pll->pll_e, pll->div); pll->pll_m, pll->pll_n, pll->pll_e, pll->div);
} }
static void __rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds,
unsigned int freq, bool dot_clock_only) unsigned int freq, bool dot_clock_only)
{ {
struct pll_info pll = { .diff = (unsigned long)-1 }; struct pll_info pll = { .diff = (unsigned long)-1 };
...@@ -305,52 +305,8 @@ static void __rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, ...@@ -305,52 +305,8 @@ static void __rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds,
rcar_lvds_write(lvds, LVDDIV, 0); rcar_lvds_write(lvds, LVDDIV, 0);
} }
static void rcar_lvds_pll_setup_d3_e3(struct rcar_lvds *lvds, unsigned int freq)
{
__rcar_lvds_pll_setup_d3_e3(lvds, freq, false);
}
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* Clock - D3/E3 only * Enable/disable
*/
int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
int ret;
if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
return -ENODEV;
dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq);
ret = pm_runtime_resume_and_get(lvds->dev);
if (ret)
return ret;
__rcar_lvds_pll_setup_d3_e3(lvds, freq, true);
return 0;
}
EXPORT_SYMBOL_GPL(rcar_lvds_pclk_enable);
void rcar_lvds_pclk_disable(struct drm_bridge *bridge)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
return;
dev_dbg(lvds->dev, "disabling LVDS PLL\n");
rcar_lvds_write(lvds, LVDPLLCR, 0);
pm_runtime_put_sync(lvds->dev);
}
EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable);
/* -----------------------------------------------------------------------------
* Bridge
*/ */
static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds, static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
...@@ -394,7 +350,7 @@ static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds, ...@@ -394,7 +350,7 @@ static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds,
return mode; return mode;
} }
static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, static void rcar_lvds_enable(struct drm_bridge *bridge,
struct drm_atomic_state *state, struct drm_atomic_state *state,
struct drm_crtc *crtc, struct drm_crtc *crtc,
struct drm_connector *connector) struct drm_connector *connector)
...@@ -410,8 +366,7 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, ...@@ -410,8 +366,7 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
/* Enable the companion LVDS encoder in dual-link mode. */ /* Enable the companion LVDS encoder in dual-link mode. */
if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion) if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion)
__rcar_lvds_atomic_enable(lvds->companion, state, crtc, rcar_lvds_enable(lvds->companion, state, crtc, connector);
connector);
/* /*
* Hardcode the channels and control signals routing for now. * Hardcode the channels and control signals routing for now.
...@@ -465,8 +420,12 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, ...@@ -465,8 +420,12 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
/* /*
* PLL clock configuration on all instances but the companion in * PLL clock configuration on all instances but the companion in
* dual-link mode. * dual-link mode.
*
* The extended PLL has been turned on by an explicit call to
* rcar_lvds_pclk_enable() from the DU driver.
*/ */
if (lvds->link_type == RCAR_LVDS_SINGLE_LINK || lvds->companion) { if ((lvds->link_type == RCAR_LVDS_SINGLE_LINK || lvds->companion) &&
!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
const struct drm_crtc_state *crtc_state = const struct drm_crtc_state *crtc_state =
drm_atomic_get_new_crtc_state(state, crtc); drm_atomic_get_new_crtc_state(state, crtc);
const struct drm_display_mode *mode = const struct drm_display_mode *mode =
...@@ -531,22 +490,7 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge, ...@@ -531,22 +490,7 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
rcar_lvds_write(lvds, LVDCR0, lvdcr0); rcar_lvds_write(lvds, LVDCR0, lvdcr0);
} }
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, static void rcar_lvds_disable(struct drm_bridge *bridge)
struct drm_bridge_state *old_bridge_state)
{
struct drm_atomic_state *state = old_bridge_state->base.state;
struct drm_connector *connector;
struct drm_crtc *crtc;
connector = drm_atomic_get_new_connector_for_encoder(state,
bridge->encoder);
crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
__rcar_lvds_atomic_enable(bridge, state, crtc, connector);
}
static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{ {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
u32 lvdcr0; u32 lvdcr0;
...@@ -578,16 +522,100 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge, ...@@ -578,16 +522,100 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
rcar_lvds_write(lvds, LVDCR0, 0); rcar_lvds_write(lvds, LVDCR0, 0);
rcar_lvds_write(lvds, LVDCR1, 0); rcar_lvds_write(lvds, LVDCR1, 0);
/* The extended PLL is turned off in rcar_lvds_pclk_disable(). */
if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL))
rcar_lvds_write(lvds, LVDPLLCR, 0); rcar_lvds_write(lvds, LVDPLLCR, 0);
/* Disable the companion LVDS encoder in dual-link mode. */ /* Disable the companion LVDS encoder in dual-link mode. */
if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion) if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion)
lvds->companion->funcs->atomic_disable(lvds->companion, rcar_lvds_disable(lvds->companion);
old_bridge_state);
pm_runtime_put_sync(lvds->dev); pm_runtime_put_sync(lvds->dev);
} }
/* -----------------------------------------------------------------------------
* Clock - D3/E3 only
*/
int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq,
bool dot_clk_only)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
int ret;
if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
return -ENODEV;
dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq);
ret = pm_runtime_resume_and_get(lvds->dev);
if (ret)
return ret;
rcar_lvds_pll_setup_d3_e3(lvds, freq, dot_clk_only);
return 0;
}
EXPORT_SYMBOL_GPL(rcar_lvds_pclk_enable);
void rcar_lvds_pclk_disable(struct drm_bridge *bridge, bool dot_clk_only)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
if (WARN_ON(!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)))
return;
dev_dbg(lvds->dev, "disabling LVDS PLL\n");
if (!dot_clk_only)
rcar_lvds_disable(bridge);
rcar_lvds_write(lvds, LVDPLLCR, 0);
pm_runtime_put_sync(lvds->dev);
}
EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable);
/* -----------------------------------------------------------------------------
* Bridge
*/
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct drm_atomic_state *state = old_bridge_state->base.state;
struct drm_connector *connector;
struct drm_crtc *crtc;
connector = drm_atomic_get_new_connector_for_encoder(state,
bridge->encoder);
crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
rcar_lvds_enable(bridge, state, crtc, connector);
}
static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
/*
* For D3 and E3, disabling the LVDS encoder before the DU would stall
* the DU, causing a vblank wait timeout when stopping the DU. This has
* been traced to clearing the LVEN bit, but the exact reason is
* unknown. Keep the encoder enabled, it will be disabled by an explicit
* call to rcar_lvds_pclk_disable() from the DU driver.
*
* We could clear the LVRES bit already to disable the LVDS output, but
* that's likely pointless.
*/
if (lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)
return;
rcar_lvds_disable(bridge);
}
static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge, static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
...@@ -922,14 +950,12 @@ static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = { ...@@ -922,14 +950,12 @@ static const struct rcar_lvds_device_info rcar_lvds_r8a77990_info = {
.gen = 3, .gen = 3,
.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL .quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_EXT_PLL
| RCAR_LVDS_QUIRK_DUAL_LINK, | RCAR_LVDS_QUIRK_DUAL_LINK,
.pll_setup = rcar_lvds_pll_setup_d3_e3,
}; };
static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = { static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
.gen = 3, .gen = 3,
.quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD .quirks = RCAR_LVDS_QUIRK_GEN3_LVEN | RCAR_LVDS_QUIRK_PWD
| RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK, | RCAR_LVDS_QUIRK_EXT_PLL | RCAR_LVDS_QUIRK_DUAL_LINK,
.pll_setup = rcar_lvds_pll_setup_d3_e3,
}; };
static const struct of_device_id rcar_lvds_of_table[] = { static const struct of_device_id rcar_lvds_of_table[] = {
......
...@@ -13,17 +13,21 @@ ...@@ -13,17 +13,21 @@
struct drm_bridge; struct drm_bridge;
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq); int rcar_lvds_pclk_enable(struct drm_bridge *bridge, unsigned long freq,
void rcar_lvds_pclk_disable(struct drm_bridge *bridge); bool dot_clk_only);
void rcar_lvds_pclk_disable(struct drm_bridge *bridge, bool dot_clk_only);
bool rcar_lvds_dual_link(struct drm_bridge *bridge); bool rcar_lvds_dual_link(struct drm_bridge *bridge);
bool rcar_lvds_is_connected(struct drm_bridge *bridge); bool rcar_lvds_is_connected(struct drm_bridge *bridge);
#else #else
static inline int rcar_lvds_pclk_enable(struct drm_bridge *bridge, static inline int rcar_lvds_pclk_enable(struct drm_bridge *bridge,
unsigned long freq) unsigned long freq, bool dot_clk_only)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline void rcar_lvds_pclk_disable(struct drm_bridge *bridge) { } static inline void rcar_lvds_pclk_disable(struct drm_bridge *bridge,
bool dot_clock_only)
{
}
static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge) static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge)
{ {
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment