Skip to content

Commit a59a271

Browse files
committed
drm/bridge: tc358767: convert to devm_drm_bridge_alloc() API
This is the new API for allocating DRM bridges. Converting this driver is a bit complex because the drm_bridge funcs pointer differs based on the bridge mode. So the current code does: * tc_probe() * devm_kzalloc() private struct embedding drm_bridge * call tc_probe_bridge_endpoint() which * parses DT description into struct fields * computes the mode * calls different bridge init functions based on the mode * each sets a different bridge.funcs pointer The new API expects the funcs pointer to be known at alloc time, which does not fit in the current code structure. Solve this by splitting tc_probe_bridge_endpoint() in two functions: * tc_probe_get_mode(), computing the mode without needing the private driver structure * tc_probe_bridge_endpoint(), only initializing the endpoints So now the mode is known before allocation and so is the funcs pointer, while all other operations are still happening after allocation, directly into the private struct data, as they used to. The new code flow is: * tc_probe() * tc_probe_get_mode() * parses DT description * computes and returns the mode * based onf the mode, pick the funcs pointer * devm_drm_bridfge_alloc(..., funcs) * call tc_probe_bridge_endpoint() which * calls different bridge init functions based on the mode * these don't set the funcs pointer, it was done by _alloc This solution is chosen to minimize the changes in the driver logical code flow. The drawback is we now iterate twice over the endpoints during probe. Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Link: https://lore.kernel.org/r/20250528-drm-bridge-convert-to-alloc-api-v4-1-f04e698c9a77@bootlin.com Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
1 parent 1a45ef0 commit a59a271

1 file changed

Lines changed: 40 additions & 16 deletions

File tree

drivers/gpu/drm/bridge/tc358767.c

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,14 @@
344344
#define COLOR_BAR_MODE_BARS 2
345345
#define PLL_DBG 0x0a04
346346

347+
enum tc_mode {
348+
mode_dpi_to_edp = BIT(1) | BIT(2),
349+
mode_dpi_to_dp = BIT(1),
350+
mode_dsi_to_edp = BIT(0) | BIT(2),
351+
mode_dsi_to_dp = BIT(0),
352+
mode_dsi_to_dpi = BIT(0) | BIT(1),
353+
};
354+
347355
static bool tc_test_pattern;
348356
module_param_named(test, tc_test_pattern, bool, 0644);
349357

@@ -2327,7 +2335,6 @@ static int tc_probe_dpi_bridge_endpoint(struct tc_data *tc)
23272335
if (bridge) {
23282336
tc->panel_bridge = bridge;
23292337
tc->bridge.type = DRM_MODE_CONNECTOR_DPI;
2330-
tc->bridge.funcs = &tc_dpi_bridge_funcs;
23312338

23322339
return 0;
23332340
}
@@ -2360,25 +2367,18 @@ static int tc_probe_edp_bridge_endpoint(struct tc_data *tc)
23602367
tc->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
23612368
}
23622369

2363-
tc->bridge.funcs = &tc_edp_bridge_funcs;
23642370
if (tc->hpd_pin >= 0)
23652371
tc->bridge.ops |= DRM_BRIDGE_OP_DETECT;
23662372
tc->bridge.ops |= DRM_BRIDGE_OP_EDID;
23672373

23682374
return 0;
23692375
}
23702376

2371-
static int tc_probe_bridge_endpoint(struct tc_data *tc)
2377+
static enum tc_mode tc_probe_get_mode(struct device *dev)
23722378
{
2373-
struct device *dev = tc->dev;
23742379
struct of_endpoint endpoint;
23752380
struct device_node *node = NULL;
2376-
const u8 mode_dpi_to_edp = BIT(1) | BIT(2);
2377-
const u8 mode_dpi_to_dp = BIT(1);
2378-
const u8 mode_dsi_to_edp = BIT(0) | BIT(2);
2379-
const u8 mode_dsi_to_dp = BIT(0);
2380-
const u8 mode_dsi_to_dpi = BIT(0) | BIT(1);
2381-
u8 mode = 0;
2381+
enum tc_mode mode = 0;
23822382

23832383
/*
23842384
* Determine bridge configuration.
@@ -2401,7 +2401,27 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc)
24012401
return -EINVAL;
24022402
}
24032403
mode |= BIT(endpoint.port);
2404+
}
2405+
2406+
if (mode != mode_dpi_to_edp &&
2407+
mode != mode_dpi_to_dp &&
2408+
mode != mode_dsi_to_dpi &&
2409+
mode != mode_dsi_to_edp &&
2410+
mode != mode_dsi_to_dp) {
2411+
dev_warn(dev, "Invalid mode (0x%x) is not supported!\n", mode);
2412+
return -EINVAL;
2413+
}
2414+
2415+
return mode;
2416+
}
24042417

2418+
static int tc_probe_bridge_endpoint(struct tc_data *tc, enum tc_mode mode)
2419+
{
2420+
struct device *dev = tc->dev;
2421+
struct of_endpoint endpoint;
2422+
struct device_node *node = NULL;
2423+
2424+
for_each_endpoint_of_node(dev->of_node, node) {
24052425
if (endpoint.port == 2) {
24062426
of_property_read_u8_array(node, "toshiba,pre-emphasis",
24072427
tc->pre_emphasis,
@@ -2427,24 +2447,28 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc)
24272447
return tc_probe_edp_bridge_endpoint(tc);
24282448
}
24292449

2430-
dev_warn(dev, "Invalid mode (0x%x) is not supported!\n", mode);
2431-
2450+
/* Should never happen, mode was validated by tc_probe_get_mode() */
24322451
return -EINVAL;
24332452
}
24342453

24352454
static int tc_probe(struct i2c_client *client)
24362455
{
24372456
struct device *dev = &client->dev;
2457+
const struct drm_bridge_funcs *funcs;
24382458
struct tc_data *tc;
2459+
int mode;
24392460
int ret;
24402461

2441-
tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL);
2442-
if (!tc)
2443-
return -ENOMEM;
2462+
mode = tc_probe_get_mode(dev);
2463+
funcs = (mode == mode_dsi_to_dpi) ? &tc_dpi_bridge_funcs : &tc_edp_bridge_funcs;
2464+
2465+
tc = devm_drm_bridge_alloc(dev, struct tc_data, bridge, funcs);
2466+
if (IS_ERR(tc))
2467+
return PTR_ERR(tc);
24442468

24452469
tc->dev = dev;
24462470

2447-
ret = tc_probe_bridge_endpoint(tc);
2471+
ret = tc_probe_bridge_endpoint(tc, mode);
24482472
if (ret)
24492473
return ret;
24502474

0 commit comments

Comments
 (0)