Skip to content

Commit 5d74a18

Browse files
committed
drm/vc4: Convert vc4_dsi to using a bridge instead of encoder.
Remove the encoder functions, and create a bridge attached to this dumb encoder which implements the same functionality. As a bridge has state which an encoder doesn't, we need to add the state management functions as well. As there is no bridge atomic_mode_set, move the initialisation code that was in mode_set into _pre_enable. The code to actually enable and disable sending video are split from the general control into _enable and _disable. Signed-off-by: Dave Stevenson <[email protected]>
1 parent e9b590c commit 5d74a18

File tree

1 file changed

+90
-34
lines changed

1 file changed

+90
-34
lines changed

drivers/gpu/drm/vc4/vc4_dsi.c

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ struct vc4_dsi {
554554
struct mipi_dsi_host dsi_host;
555555
struct drm_encoder *encoder;
556556
struct drm_bridge *out_bridge;
557+
struct drm_bridge bridge;
557558

558559
void __iomem *regs;
559560

@@ -655,6 +656,12 @@ to_vc4_dsi_encoder(struct drm_encoder *encoder)
655656
return container_of(encoder, struct vc4_dsi_encoder, base.base);
656657
}
657658

659+
static inline struct vc4_dsi *
660+
bridge_to_vc4_dsi(struct drm_bridge *bridge)
661+
{
662+
return container_of(bridge, struct vc4_dsi, bridge);
663+
}
664+
658665
static const struct debugfs_reg32 dsi0_regs[] = {
659666
VC4_REG32(DSI0_CTRL),
660667
VC4_REG32(DSI0_STAT),
@@ -792,11 +799,21 @@ dsi_esc_timing(u32 ns)
792799
return DIV_ROUND_UP(ns, ESC_TIME_NS);
793800
}
794801

795-
static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
796-
struct drm_atomic_state *state)
802+
static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
803+
struct drm_bridge_state *state)
804+
{
805+
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
806+
u32 disp0_ctrl;
807+
808+
disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
809+
disp0_ctrl &= ~DSI_DISP0_ENABLE;
810+
DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
811+
}
812+
813+
static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge,
814+
struct drm_bridge_state *state)
797815
{
798-
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
799-
struct vc4_dsi *dsi = vc4_encoder->dsi;
816+
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
800817
struct device *dev = &dsi->pdev->dev;
801818

802819
vc4_dsi_ulps(dsi, true);
@@ -821,12 +838,11 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
821838
* higher-than-expected clock rate to the panel, but that's what the
822839
* firmware does too.
823840
*/
824-
static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
825-
const struct drm_display_mode *mode,
826-
struct drm_display_mode *adjusted_mode)
841+
static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
842+
const struct drm_display_mode *mode,
843+
struct drm_display_mode *adjusted_mode)
827844
{
828-
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
829-
struct vc4_dsi *dsi = vc4_encoder->dsi;
845+
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
830846
struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
831847
unsigned long parent_rate = clk_get_rate(phy_parent);
832848
unsigned long pixel_clock_hz = mode->clock * 1000;
@@ -858,16 +874,18 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
858874
return true;
859875
}
860876

861-
static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
862-
struct drm_crtc_state *crtc_state,
863-
struct drm_connector_state *conn_state)
877+
static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
878+
struct drm_bridge_state *old_state)
864879
{
865-
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
866-
struct vc4_dsi *dsi = vc4_encoder->dsi;
880+
struct drm_atomic_state *state = old_state->base.state;
881+
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
882+
const struct drm_crtc_state *crtc_state;
867883
struct device *dev = &dsi->pdev->dev;
868884
const struct drm_display_mode *mode;
885+
struct drm_connector *connector;
869886
bool debug_dump_regs = false;
870887
unsigned long hs_clock;
888+
struct drm_crtc *crtc;
871889
u32 ui_ns;
872890
/* Minimum LP state duration in escape clock cycles. */
873891
u32 lpx = dsi_esc_timing(60);
@@ -888,6 +906,14 @@ static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
888906
drm_print_regset32(&p, &dsi->regset);
889907
}
890908

909+
/*
910+
* Retrieve the CRTC adjusted mode. This requires a little dance to go
911+
* from the bridge to the encoder, to the connector and to the CRTC.
912+
*/
913+
connector = drm_atomic_get_new_connector_for_encoder(state,
914+
bridge->encoder);
915+
crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
916+
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
891917
mode = &crtc_state->adjusted_mode;
892918

893919
pixel_clock_hz = mode->clock * 1000;
@@ -1102,14 +1128,6 @@ static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
11021128
~DSI_PORT_BIT(PHY_AFEC0_RESET));
11031129

11041130
vc4_dsi_ulps(dsi, false);
1105-
}
1106-
1107-
static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
1108-
struct drm_atomic_state *state)
1109-
{
1110-
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
1111-
struct vc4_dsi *dsi = vc4_encoder->dsi;
1112-
bool debug_dump_regs = false;
11131131

11141132
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
11151133
DSI_PORT_WRITE(DISP0_CTRL,
@@ -1118,13 +1136,23 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
11181136
VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) |
11191137
VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME,
11201138
DSI_DISP0_LP_STOP_CTRL) |
1121-
DSI_DISP0_ST_END |
1122-
DSI_DISP0_ENABLE);
1139+
DSI_DISP0_ST_END);
11231140
} else {
11241141
DSI_PORT_WRITE(DISP0_CTRL,
1125-
DSI_DISP0_COMMAND_MODE |
1126-
DSI_DISP0_ENABLE);
1142+
DSI_DISP0_COMMAND_MODE);
11271143
}
1144+
}
1145+
1146+
static void vc4_dsi_bridge_enable(struct drm_bridge *bridge,
1147+
struct drm_bridge_state *old_state)
1148+
{
1149+
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
1150+
bool debug_dump_regs = false;
1151+
u32 disp0_ctrl;
1152+
1153+
disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
1154+
disp0_ctrl |= DSI_DISP0_ENABLE;
1155+
DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
11281156

11291157
if (debug_dump_regs) {
11301158
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
@@ -1133,6 +1161,16 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
11331161
}
11341162
}
11351163

1164+
static int vc4_dsi_bridge_attach(struct drm_bridge *bridge,
1165+
enum drm_bridge_attach_flags flags)
1166+
{
1167+
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
1168+
1169+
/* Attach the panel or bridge to the dsi bridge */
1170+
return drm_bridge_attach(bridge->encoder, dsi->out_bridge,
1171+
&dsi->bridge, flags);
1172+
}
1173+
11361174
static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
11371175
const struct mipi_dsi_msg *msg)
11381176
{
@@ -1309,6 +1347,7 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host,
13091347
struct mipi_dsi_device *device)
13101348
{
13111349
struct vc4_dsi *dsi = host_to_dsi(host);
1350+
int ret;
13121351

13131352
dsi->lanes = device->lanes;
13141353
dsi->channel = device->channel;
@@ -1343,7 +1382,15 @@ static int vc4_dsi_host_attach(struct mipi_dsi_host *host,
13431382
return 0;
13441383
}
13451384

1346-
return component_add(&dsi->pdev->dev, &vc4_dsi_ops);
1385+
drm_bridge_add(&dsi->bridge);
1386+
1387+
ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops);
1388+
if (ret) {
1389+
drm_bridge_remove(&dsi->bridge);
1390+
return ret;
1391+
}
1392+
1393+
return 0;
13471394
}
13481395

13491396
static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
@@ -1352,6 +1399,7 @@ static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
13521399
struct vc4_dsi *dsi = host_to_dsi(host);
13531400

13541401
component_del(&dsi->pdev->dev, &vc4_dsi_ops);
1402+
drm_bridge_remove(&dsi->bridge);
13551403
return 0;
13561404
}
13571405

@@ -1361,11 +1409,16 @@ static const struct mipi_dsi_host_ops vc4_dsi_host_ops = {
13611409
.transfer = vc4_dsi_host_transfer,
13621410
};
13631411

1364-
static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
1365-
.atomic_disable = vc4_dsi_encoder_disable,
1366-
.atomic_enable = vc4_dsi_encoder_enable,
1367-
.mode_fixup = vc4_dsi_encoder_mode_fixup,
1368-
.atomic_mode_set = vc4_dsi_encoder_mode_set,
1412+
static const struct drm_bridge_funcs vc4_dsi_bridge_funcs = {
1413+
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
1414+
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
1415+
.atomic_reset = drm_atomic_helper_bridge_reset,
1416+
.atomic_pre_enable = vc4_dsi_bridge_pre_enable,
1417+
.atomic_enable = vc4_dsi_bridge_enable,
1418+
.atomic_disable = vc4_dsi_bridge_disable,
1419+
.atomic_post_disable = vc4_dsi_bridge_post_disable,
1420+
.attach = vc4_dsi_bridge_attach,
1421+
.mode_fixup = vc4_dsi_bridge_mode_fixup,
13691422
};
13701423

13711424
static const struct vc4_dsi_variant bcm2711_dsi1_variant = {
@@ -1691,9 +1744,8 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
16911744
goto err_free_dma;
16921745

16931746
drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI);
1694-
drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
16951747

1696-
ret = drm_bridge_attach(dsi->encoder, dsi->out_bridge, NULL, 0);
1748+
ret = drm_bridge_attach(dsi->encoder, &dsi->bridge, NULL, 0);
16971749
if (ret) {
16981750
dev_err(dev, "bridge attach failed: %d\n", ret);
16991751
goto err_free_dma;
@@ -1755,6 +1807,10 @@ static int vc4_dsi_dev_probe(struct platform_device *pdev)
17551807
return -ENOMEM;
17561808
dev_set_drvdata(dev, dsi);
17571809

1810+
dsi->bridge.funcs = &vc4_dsi_bridge_funcs;
1811+
dsi->bridge.of_node = dev->of_node;
1812+
dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
1813+
17581814
dsi->pdev = pdev;
17591815
dsi->dsi_host.ops = &vc4_dsi_host_ops;
17601816
dsi->dsi_host.dev = dev;

0 commit comments

Comments
 (0)