1
0
Fork 0

R-Car DU changes for v5.3:

- R8A774A1 SoC support
 - LVDS dual-link mode support
 - Support for additional formats
 - Misc fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQJWBAABCgBAFiEEvZRkio5H7O2/GZsYYiVdKZ4oCyQFAlz7uhsiHGxhdXJlbnQu
 cGluY2hhcnRAaWRlYXNvbmJvYXJkLmNvbQAKCRBiJV0pnigLJEXWD/9Q92VnI5cg
 ITqmrxsN8O9ArFBoKyb6UOyUWaz7QsQeQZw78oSxT7vKtBbBK8AYlcjmuxBZPZqe
 lu1PVcdd5/C+wU4Izp+TMbT2rKDSP2rK4fk5T40uYfkxeFvYAyBA+duRbnVjvWRW
 n34bFuI+lfsW1LjBjVzCTG6aWfiR4/gcZTdSSH4+iL+k39nnu+WE5JdJWI54s8Fy
 X1W7szMASf3/psj6/6kAhEcvfo9D+p/EPjOw/mACGsUdZ1o9Fj4abCBHNRGEN7Dx
 jypZPTRU/V3z8/YrEQfAezWlFUouCyEwL1JMnylfJpdAzncwh1y7lk7vc52EmE+l
 gKL0BYl04A7u3prXAtjYZXFNoXaDFQ2MqguZ73LLQ1izSdJxQJK6bGEtwssuSn/p
 AUHCp9Je/E+g4XObCFToXgLzR4WK08yXmIGkNACYQEB3hNtyEenA4YKja4GadI+l
 wz4/iYWE/1/jhUb9oWVAJuc34+bmv18vD4r3poLZWjtWjTkOZLJpmtte2xScBkbi
 FbQL7zncc/0KbkA8ELoKDIWx07vjTBAx2Xcl1pXbbt4efBg3b1jxCI+2zJwqmbQJ
 AdGli53PmfkzJBcM9D7ETnbC+/LHCF1i4Af9yf2zVpLUJ8o9j1gQvRPSqf5Rnj0v
 Cfger7hNS75MYGuB26Y4K/mQ0bb60Hm2XQ==
 =VoV+
 -----END PGP SIGNATURE-----

Merge tag 'du-next-20190608-2' of git://linuxtv.org/pinchartl/media into drm-next

R-Car DU changes for v5.3:

- R8A774A1 SoC support
- LVDS dual-link mode support
- Support for additional formats
- Misc fixes

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190608134652.GE4786@pendragon.ideasonboard.com
alistair/sunxi64-5.4-dsi
Daniel Vetter 2019-06-11 10:08:48 +02:00
commit 34c8a892ec
11 changed files with 298 additions and 48 deletions

View File

@ -9,6 +9,7 @@ Required properties:
- compatible : Shall contain one of
- "renesas,r8a7743-lvds" for R8A7743 (RZ/G1M) compatible LVDS encoders
- "renesas,r8a7744-lvds" for R8A7744 (RZ/G1N) compatible LVDS encoders
- "renesas,r8a774a1-lvds" for R8A774A1 (RZ/G2M) compatible LVDS encoders
- "renesas,r8a774c0-lvds" for R8A774C0 (RZ/G2E) compatible LVDS encoders
- "renesas,r8a7790-lvds" for R8A7790 (R-Car H2) compatible LVDS encoders
- "renesas,r8a7791-lvds" for R8A7791 (R-Car M2-W) compatible LVDS encoders
@ -45,14 +46,24 @@ OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
Each port shall have a single endpoint.
Optional properties:
- renesas,companion : phandle to the companion LVDS encoder. This property is
mandatory for the first LVDS encoder on D3 and E3 SoCs, and shall point to
the second encoder to be used as a companion in dual-link mode. It shall not
be set for any other LVDS encoder.
Example:
lvds0: lvds@feb90000 {
compatible = "renesas,r8a7790-lvds";
reg = <0 0xfeb90000 0 0x1c>;
clocks = <&cpg CPG_MOD 726>;
resets = <&cpg 726>;
compatible = "renesas,r8a77990-lvds";
reg = <0 0xfeb90000 0 0x20>;
clocks = <&cpg CPG_MOD 727>;
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
resets = <&cpg 727>;
renesas,companion = <&lvds1>;
ports {
#address-cells = <1>;

View File

@ -28,6 +28,12 @@ Optional video port nodes:
- port@1: Second LVDS input port
- port@3: Second digital CMOS/TTL parallel output
The device can operate in single-link mode or dual-link mode. In single-link
mode, all pixels are received on port@0, and port@1 shall not contain any
endpoint. In dual-link mode, even-numbered pixels are received on port@0 and
odd-numbered pixels on port@1, and both port@0 and port@1 shall contain
endpoints.
Example:
--------

View File

@ -7,6 +7,7 @@ Required Properties:
- "renesas,du-r8a7744" for R8A7744 (RZ/G1N) compatible DU
- "renesas,du-r8a7745" for R8A7745 (RZ/G1E) compatible DU
- "renesas,du-r8a77470" for R8A77470 (RZ/G1C) compatible DU
- "renesas,du-r8a774a1" for R8A774A1 (RZ/G2M) compatible DU
- "renesas,du-r8a774c0" for R8A774C0 (RZ/G2E) compatible DU
- "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
- "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
@ -58,6 +59,7 @@ corresponding to each DU output.
R8A7744 (RZ/G1N) DPAD 0 LVDS 0 - -
R8A7745 (RZ/G1E) DPAD 0 DPAD 1 - -
R8A77470 (RZ/G1C) DPAD 0 DPAD 1 LVDS 0 -
R8A774A1 (RZ/G2M) DPAD 0 HDMI 0 LVDS 0 -
R8A774C0 (RZ/G2E) DPAD 0 LVDS 0 LVDS 1 -
R8A7779 (R-Car H1) DPAD 0 DPAD 1 - -
R8A7790 (R-Car H2) DPAD 0 LVDS 0 LVDS 1 -

View File

@ -33,6 +33,8 @@ struct thc63_dev {
struct drm_bridge bridge;
struct drm_bridge *next;
struct drm_bridge_timings timings;
};
static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge)
@ -50,15 +52,28 @@ static int thc63_attach(struct drm_bridge *bridge)
static enum drm_mode_status thc63_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct thc63_dev *thc63 = to_thc63(bridge);
unsigned int min_freq;
unsigned int max_freq;
/*
* The THC63LVD1024 clock frequency range is 8 to 135 MHz in single-in
* mode. Note that the limits are different in dual-in, single-out mode,
* and will need to be adjusted accordingly.
* The THC63LVD1024 pixel rate range is 8 to 135 MHz in all modes but
* dual-in, single-out where it is 40 to 150 MHz. As dual-in, dual-out
* isn't supported by the driver yet, simply derive the limits from the
* input mode.
*/
if (mode->clock < 8000)
if (thc63->timings.dual_link) {
min_freq = 40000;
max_freq = 150000;
} else {
min_freq = 8000;
max_freq = 135000;
}
if (mode->clock < min_freq)
return MODE_CLOCK_LOW;
if (mode->clock > 135000)
if (mode->clock > max_freq)
return MODE_CLOCK_HIGH;
return MODE_OK;
@ -103,19 +118,19 @@ static const struct drm_bridge_funcs thc63_bridge_func = {
static int thc63_parse_dt(struct thc63_dev *thc63)
{
struct device_node *thc63_out;
struct device_node *endpoint;
struct device_node *remote;
thc63_out = of_graph_get_endpoint_by_regs(thc63->dev->of_node,
THC63_RGB_OUT0, -1);
if (!thc63_out) {
endpoint = of_graph_get_endpoint_by_regs(thc63->dev->of_node,
THC63_RGB_OUT0, -1);
if (!endpoint) {
dev_err(thc63->dev, "Missing endpoint in port@%u\n",
THC63_RGB_OUT0);
return -ENODEV;
}
remote = of_graph_get_remote_port_parent(thc63_out);
of_node_put(thc63_out);
remote = of_graph_get_remote_port_parent(endpoint);
of_node_put(endpoint);
if (!remote) {
dev_err(thc63->dev, "Endpoint in port@%u unconnected\n",
THC63_RGB_OUT0);
@ -134,6 +149,22 @@ static int thc63_parse_dt(struct thc63_dev *thc63)
if (!thc63->next)
return -EPROBE_DEFER;
endpoint = of_graph_get_endpoint_by_regs(thc63->dev->of_node,
THC63_LVDS_IN1, -1);
if (endpoint) {
remote = of_graph_get_remote_port_parent(endpoint);
of_node_put(endpoint);
if (remote) {
if (of_device_is_available(remote))
thc63->timings.dual_link = true;
of_node_put(remote);
}
}
dev_dbg(thc63->dev, "operating in %s-link mode\n",
thc63->timings.dual_link ? "dual" : "single");
return 0;
}
@ -190,6 +221,7 @@ static int thc63_probe(struct platform_device *pdev)
thc63->bridge.driver_private = thc63;
thc63->bridge.of_node = pdev->dev.of_node;
thc63->bridge.funcs = &thc63_bridge_func;
thc63->bridge.timings = &thc63->timings;
drm_bridge_add(&thc63->bridge);

View File

@ -102,6 +102,35 @@ static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
},
};
static const struct rcar_du_device_info rcar_du_r8a774a1_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_VSP1_SOURCE
| RCAR_DU_FEATURE_INTERLACED
| RCAR_DU_FEATURE_TVM_SYNC,
.channels_mask = BIT(2) | BIT(1) | BIT(0),
.routes = {
/*
* R8A774A1 has one RGB output, one LVDS output and one HDMI
* output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(2),
.port = 0,
},
[RCAR_DU_OUTPUT_HDMI0] = {
.possible_crtcs = BIT(1),
.port = 1,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.port = 2,
},
},
.num_lvds = 1,
.dpll_mask = BIT(1),
};
static const struct rcar_du_device_info rcar_du_r8a774c0_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
@ -386,6 +415,7 @@ static const struct of_device_id rcar_du_of_table[] = {
{ .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info },
{ .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
{ .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info },
{ .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info },
{ .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info },
{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },

View File

@ -16,6 +16,7 @@
#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
#include "rcar_du_kms.h"
#include "rcar_lvds.h"
/* -----------------------------------------------------------------------------
* Encoder
@ -97,6 +98,17 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
}
}
/*
* On Gen3 skip the LVDS1 output if the LVDS1 encoder is used as a
* companion for LVDS0 in dual-link mode.
*/
if (rcdu->info->gen >= 3 && output == RCAR_DU_OUTPUT_LVDS1) {
if (rcar_lvds_dual_link(bridge)) {
ret = -ENOLINK;
goto done;
}
}
ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
DRM_MODE_ENCODER_NONE, NULL);
if (ret < 0)

View File

@ -123,6 +123,66 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
.v4l2 = V4L2_PIX_FMT_XRGB444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_RGBA4444,
.v4l2 = V4L2_PIX_FMT_RGBA444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_RGBX4444,
.v4l2 = V4L2_PIX_FMT_RGBX444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_ABGR4444,
.v4l2 = V4L2_PIX_FMT_ABGR444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_XBGR4444,
.v4l2 = V4L2_PIX_FMT_XBGR444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_BGRA4444,
.v4l2 = V4L2_PIX_FMT_BGRA444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_BGRX4444,
.v4l2 = V4L2_PIX_FMT_BGRX444,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_RGBA5551,
.v4l2 = V4L2_PIX_FMT_RGBA555,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_RGBX5551,
.v4l2 = V4L2_PIX_FMT_RGBX555,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_ABGR1555,
.v4l2 = V4L2_PIX_FMT_ABGR555,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_XBGR1555,
.v4l2 = V4L2_PIX_FMT_XBGR555,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_BGRA5551,
.v4l2 = V4L2_PIX_FMT_BGRA555,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_BGRX5551,
.v4l2 = V4L2_PIX_FMT_BGRX555,
.bpp = 16,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_BGR888,
.v4l2 = V4L2_PIX_FMT_RGB24,
@ -133,6 +193,26 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
.v4l2 = V4L2_PIX_FMT_BGR24,
.bpp = 24,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_RGBA8888,
.v4l2 = V4L2_PIX_FMT_BGRA32,
.bpp = 32,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_RGBX8888,
.v4l2 = V4L2_PIX_FMT_BGRX32,
.bpp = 32,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_ABGR8888,
.v4l2 = V4L2_PIX_FMT_RGBA32,
.bpp = 32,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_XBGR8888,
.v4l2 = V4L2_PIX_FMT_RGBX32,
.bpp = 32,
.planes = 1,
}, {
.fourcc = DRM_FORMAT_BGRA8888,
.v4l2 = V4L2_PIX_FMT_ARGB32,
@ -378,7 +458,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
}
ret = rcar_du_encoder_init(rcdu, output, entity);
if (ret && ret != -EPROBE_DEFER)
if (ret && ret != -EPROBE_DEFER && ret != -ENOLINK)
dev_warn(rcdu->dev,
"failed to initialize encoder %pOF on output %u (%d), skipping\n",
entity, output, ret);

View File

@ -14,6 +14,7 @@
#include "rcar_du_crtc.h"
#include "rcar_du_drv.h"
#include "rcar_du_kms.h"
#include "rcar_du_writeback.h"
/**
* struct rcar_du_wb_conn_state - Driver-specific writeback connector state

View File

@ -63,10 +63,12 @@ struct rcar_lvds {
struct clk *extal; /* External clock */
struct clk *dotclkin[2]; /* External DU clocks */
} clocks;
bool enabled;
struct drm_display_mode display_mode;
enum rcar_lvds_mode mode;
struct drm_bridge *companion;
bool dual_link;
};
#define bridge_to_rcar_lvds(bridge) \
@ -368,15 +370,12 @@ int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq)
dev_dbg(lvds->dev, "enabling LVDS PLL, freq=%luHz\n", freq);
WARN_ON(lvds->enabled);
ret = clk_prepare_enable(lvds->clocks.mod);
if (ret < 0)
return ret;
__rcar_lvds_pll_setup_d3_e3(lvds, freq, true);
lvds->enabled = true;
return 0;
}
EXPORT_SYMBOL_GPL(rcar_lvds_clk_enable);
@ -390,13 +389,9 @@ void rcar_lvds_clk_disable(struct drm_bridge *bridge)
dev_dbg(lvds->dev, "disabling LVDS PLL\n");
WARN_ON(!lvds->enabled);
rcar_lvds_write(lvds, LVDPLLCR, 0);
clk_disable_unprepare(lvds->clocks.mod);
lvds->enabled = false;
}
EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable);
@ -408,21 +403,18 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
const struct drm_display_mode *mode = &lvds->display_mode;
/*
* FIXME: We should really retrieve the CRTC through the state, but how
* do we get a state pointer?
*/
struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
u32 lvdhcr;
u32 lvdcr0;
int ret;
WARN_ON(lvds->enabled);
ret = clk_prepare_enable(lvds->clocks.mod);
if (ret < 0)
return;
/* Enable the companion LVDS encoder in dual-link mode. */
if (lvds->dual_link && lvds->companion)
lvds->companion->funcs->enable(lvds->companion);
/*
* Hardcode the channels and control signals routing for now.
*
@ -445,17 +437,33 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) {
/* Disable dual-link mode. */
rcar_lvds_write(lvds, LVDSTRIPE, 0);
/*
* Configure vertical stripe based on the mode of operation of
* the connected device.
*/
rcar_lvds_write(lvds, LVDSTRIPE,
lvds->dual_link ? LVDSTRIPE_ST_ON : 0);
}
/* PLL clock configuration. */
lvds->info->pll_setup(lvds, mode->clock * 1000);
/*
* PLL clock configuration on all instances but the companion in
* dual-link mode.
*/
if (!lvds->dual_link || lvds->companion)
lvds->info->pll_setup(lvds, mode->clock * 1000);
/* Set the LVDS mode and select the input. */
lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
if (drm_crtc_index(crtc) == 2)
lvdcr0 |= LVDCR0_DUSEL;
if (lvds->bridge.encoder) {
/*
* FIXME: We should really retrieve the CRTC through the state,
* but how do we get a state pointer?
*/
if (drm_crtc_index(lvds->bridge.encoder->crtc) == 2)
lvdcr0 |= LVDCR0_DUSEL;
}
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
/* Turn all the channels on. */
@ -507,16 +515,12 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
drm_panel_prepare(lvds->panel);
drm_panel_enable(lvds->panel);
}
lvds->enabled = true;
}
static void rcar_lvds_disable(struct drm_bridge *bridge)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
WARN_ON(!lvds->enabled);
if (lvds->panel) {
drm_panel_disable(lvds->panel);
drm_panel_unprepare(lvds->panel);
@ -526,9 +530,11 @@ static void rcar_lvds_disable(struct drm_bridge *bridge)
rcar_lvds_write(lvds, LVDCR1, 0);
rcar_lvds_write(lvds, LVDPLLCR, 0);
clk_disable_unprepare(lvds->clocks.mod);
/* Disable the companion LVDS encoder in dual-link mode. */
if (lvds->dual_link && lvds->companion)
lvds->companion->funcs->disable(lvds->companion);
lvds->enabled = false;
clk_disable_unprepare(lvds->clocks.mod);
}
static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge,
@ -592,8 +598,6 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge,
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
WARN_ON(lvds->enabled);
lvds->display_mode = *adjusted_mode;
rcar_lvds_get_lvds_mode(lvds);
@ -646,10 +650,57 @@ static const struct drm_bridge_funcs rcar_lvds_bridge_ops = {
.mode_set = rcar_lvds_mode_set,
};
bool rcar_lvds_dual_link(struct drm_bridge *bridge)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
return lvds->dual_link;
}
EXPORT_SYMBOL_GPL(rcar_lvds_dual_link);
/* -----------------------------------------------------------------------------
* Probe & Remove
*/
static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds)
{
const struct of_device_id *match;
struct device_node *companion;
struct device *dev = lvds->dev;
int ret = 0;
/* Locate the companion LVDS encoder for dual-link operation, if any. */
companion = of_parse_phandle(dev->of_node, "renesas,companion", 0);
if (!companion) {
dev_err(dev, "Companion LVDS encoder not found\n");
return -ENXIO;
}
/*
* Sanity check: the companion encoder must have the same compatible
* string.
*/
match = of_match_device(dev->driver->of_match_table, dev);
if (!of_device_is_compatible(companion, match->compatible)) {
dev_err(dev, "Companion LVDS encoder is invalid\n");
ret = -ENXIO;
goto done;
}
lvds->companion = of_drm_find_bridge(companion);
if (!lvds->companion) {
ret = -EPROBE_DEFER;
goto done;
}
dev_dbg(dev, "Found companion encoder %pOF\n", companion);
done:
of_node_put(companion);
return ret;
}
static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
{
struct device_node *local_output = NULL;
@ -700,14 +751,26 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
if (is_bridge) {
lvds->next_bridge = of_drm_find_bridge(remote);
if (!lvds->next_bridge)
if (!lvds->next_bridge) {
ret = -EPROBE_DEFER;
goto done;
}
if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK)
lvds->dual_link = lvds->next_bridge->timings
? lvds->next_bridge->timings->dual_link
: false;
} else {
lvds->panel = of_drm_find_panel(remote);
if (IS_ERR(lvds->panel))
if (IS_ERR(lvds->panel)) {
ret = PTR_ERR(lvds->panel);
goto done;
}
}
if (lvds->dual_link)
ret = rcar_lvds_parse_dt_companion(lvds);
done:
of_node_put(local_output);
of_node_put(remote_input);
@ -793,7 +856,6 @@ static int rcar_lvds_probe(struct platform_device *pdev)
lvds->dev = &pdev->dev;
lvds->info = of_device_get_match_data(&pdev->dev);
lvds->enabled = false;
ret = rcar_lvds_parse_dt(lvds);
if (ret < 0)
@ -866,6 +928,7 @@ static const struct rcar_lvds_device_info rcar_lvds_r8a77995_info = {
static const struct of_device_id rcar_lvds_of_table[] = {
{ .compatible = "renesas,r8a7743-lvds", .data = &rcar_lvds_gen2_info },
{ .compatible = "renesas,r8a7744-lvds", .data = &rcar_lvds_gen2_info },
{ .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info },
{ .compatible = "renesas,r8a774c0-lvds", .data = &rcar_lvds_r8a77990_info },
{ .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_r8a7790_info },
{ .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info },

View File

@ -15,6 +15,7 @@ struct drm_bridge;
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
int rcar_lvds_clk_enable(struct drm_bridge *bridge, unsigned long freq);
void rcar_lvds_clk_disable(struct drm_bridge *bridge);
bool rcar_lvds_dual_link(struct drm_bridge *bridge);
#else
static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge,
unsigned long freq)
@ -22,6 +23,10 @@ static inline int rcar_lvds_clk_enable(struct drm_bridge *bridge,
return -ENOSYS;
}
static inline void rcar_lvds_clk_disable(struct drm_bridge *bridge) { }
static inline bool rcar_lvds_dual_link(struct drm_bridge *bridge)
{
return false;
}
#endif /* CONFIG_DRM_RCAR_LVDS */
#endif /* __RCAR_LVDS_H__ */

View File

@ -265,6 +265,14 @@ struct drm_bridge_timings {
* input signal after the clock edge.
*/
u32 hold_time_ps;
/**
* @dual_link:
*
* True if the bus operates in dual-link mode. The exact meaning is
* dependent on the bus type. For LVDS buses, this indicates that even-
* and odd-numbered pixels are received on separate links.
*/
bool dual_link;
};
/**