Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/tidss: Move OLDI mode validation to OLDI bridge mode_valid hook

After integrating OLDI support[0], it is necessary to identify which VP
instances use OLDI, since the OLDI driver owns the video port clock
(as a serial clock). Clock operations on these VPs must be delegated to
the OLDI driver, not handled by the TIDSS driver. This issue also
emerged in upstream discussions when DSI-related clock management was
attempted in the TIDSS driver[1].

To address this, add an 'is_ext_vp_clk' array to the 'tidss_device'
structure, marking a VP as 'true' during 'tidss_oldi_init()' and as
'false' during 'tidss_oldi_deinit()'. TIDSS then uses 'is_ext_vp_clk'
to skip clock validation checks in 'dispc_vp_mode_valid()' for VPs
under OLDI control.

Since OLDI uses the DSS VP clock directly as a serial interface and
manages its own rate, mode validation should be implemented in the OLDI
bridge's 'mode_valid' hook. This patch adds that logic, ensuring proper
delegation and avoiding spurious clock handling in the TIDSS driver.

[0]: https://lore.kernel.org/all/20250528122544.817829-1-aradhya.bhatia@linux.dev/
[1]: https://lore.kernel.org/all/DA6TT575Z82D.3MPK8HG5GRL8U@kernel.org/

Fixes: 7246e0929945 ("drm/tidss: Add OLDI bridge support")
Tested-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Devarsh Thakkar <devarsht@ti.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Jayesh Choudhary <j-choudhary@ti.com>
Signed-off-by: Swamil Jain <s-jain1@ti.com>
Link: https://patch.msgid.link/20251104151422.307162-3-s-jain1@ti.com
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Link: https://patch.msgid.link/ffd5ebe03391b3c01e616c0c844a4b8ddecede36.1762513240.git.jani.nikula@intel.com

authored by

Jayesh Choudhary and committed by
Tomi Valkeinen
86db652f 527e1325

+31
+7
drivers/gpu/drm/tidss/tidss_dispc.c
··· 1306 1306 { 1307 1307 unsigned long round_clock; 1308 1308 1309 + /* 1310 + * For VP's with external clocking, clock operations must be 1311 + * delegated to respective driver, so we skip the check here. 1312 + */ 1313 + if (dispc->tidss->is_ext_vp_clk[hw_videoport]) 1314 + return 0; 1315 + 1309 1316 round_clock = clk_round_rate(dispc->vp_clk[hw_videoport], clock); 1310 1317 /* 1311 1318 * To keep the check consistent with dispc_vp_set_clk_rate(), we
+2
drivers/gpu/drm/tidss/tidss_drv.h
··· 24 24 25 25 const struct dispc_features *feat; 26 26 struct dispc_device *dispc; 27 + bool is_ext_vp_clk[TIDSS_MAX_PORTS]; 28 + 27 29 28 30 unsigned int num_crtcs; 29 31 struct drm_crtc *crtcs[TIDSS_MAX_PORTS];
+22
drivers/gpu/drm/tidss/tidss_oldi.c
··· 309 309 return input_fmts; 310 310 } 311 311 312 + static enum drm_mode_status 313 + tidss_oldi_mode_valid(struct drm_bridge *bridge, 314 + const struct drm_display_info *info, 315 + const struct drm_display_mode *mode) 316 + { 317 + struct tidss_oldi *oldi = drm_bridge_to_tidss_oldi(bridge); 318 + unsigned long round_clock; 319 + 320 + round_clock = clk_round_rate(oldi->serial, mode->clock * 7 * 1000); 321 + /* 322 + * To keep the check consistent with dispc_vp_set_clk_rate(), 323 + * we use the same 5% check here. 324 + */ 325 + if (dispc_pclk_diff(mode->clock * 7 * 1000, round_clock) > 5) 326 + return -EINVAL; 327 + 328 + return 0; 329 + } 330 + 312 331 static const struct drm_bridge_funcs tidss_oldi_bridge_funcs = { 313 332 .attach = tidss_oldi_bridge_attach, 314 333 .atomic_pre_enable = tidss_oldi_atomic_pre_enable, ··· 336 317 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, 337 318 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, 338 319 .atomic_reset = drm_atomic_helper_bridge_reset, 320 + .mode_valid = tidss_oldi_mode_valid, 339 321 }; 340 322 341 323 static int get_oldi_mode(struct device_node *oldi_tx, int *companion_instance) ··· 450 430 for (int i = 0; i < tidss->num_oldis; i++) { 451 431 if (tidss->oldis[i]) { 452 432 drm_bridge_remove(&tidss->oldis[i]->bridge); 433 + tidss->is_ext_vp_clk[tidss->oldis[i]->parent_vp] = false; 453 434 tidss->oldis[i] = NULL; 454 435 } 455 436 } ··· 601 580 oldi->bridge.timings = &default_tidss_oldi_timings; 602 581 603 582 tidss->oldis[tidss->num_oldis++] = oldi; 583 + tidss->is_ext_vp_clk[oldi->parent_vp] = true; 604 584 oldi->tidss = tidss; 605 585 606 586 drm_bridge_add(&oldi->bridge);