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: Remove max_pclk_khz and min_pclk_khz from tidss display features

The TIDSS hardware does not have independent maximum or minimum pixel
clock limits for each video port. Instead, these limits are determined
by the SoC's clock architecture. Previously, this constraint was
modeled using the 'max_pclk_khz' and 'min_pclk_khz' fields in
'dispc_features', but this approach is static and does not account for
the dynamic behavior of PLLs.

This patch removes the 'max_pclk_khz' and 'min_pclk_khz' fields from
'dispc_features'. The correct way to check if a requested mode's pixel
clock is supported is by using 'clk_round_rate()' in the 'mode_valid()'
hook. If the best frequency match for the mode clock falls within the
supported tolerance, it is approved. TIDSS supports a 5% pixel clock
tolerance, which is now reflected in the validation logic.

This change allows existing DSS-compatible drivers to be reused across
SoCs that only differ in their pixel clock characteristics. The
validation uses 'clk_round_rate()' for each mode, which may introduce
additional delay (about 3.5 ms for 30 modes), but this is generally
negligible. Users desiring faster validation may bypass these calls
selectively, for example, checking only the highest resolution mode,
as shown here[1].

[1]: https://lore.kernel.org/all/20250704094851.182131-3-j-choudhary@ti.com/

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-2-s-jain1@ti.com
[Tomi: dropped 'inline' from check_pixel_clock]
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>

authored by

Jayesh Choudhary and committed by
Tomi Valkeinen
527e1325 54c33a4f

+31 -58
+31 -55
drivers/gpu/drm/tidss/tidss_dispc.c
··· 58 58 }; 59 59 60 60 const struct dispc_features dispc_k2g_feats = { 61 - .min_pclk_khz = 4375, 62 - 63 - .max_pclk_khz = { 64 - [DISPC_VP_DPI] = 150000, 65 - }, 66 - 67 61 /* 68 62 * XXX According TRM the RGB input buffer width up to 2560 should 69 63 * work on 3 taps, but in practice it only works up to 1280. ··· 140 146 }; 141 147 142 148 const struct dispc_features dispc_am65x_feats = { 143 - .max_pclk_khz = { 144 - [DISPC_VP_DPI] = 165000, 145 - [DISPC_VP_OLDI_AM65X] = 165000, 146 - }, 147 - 148 149 .scaling = { 149 150 .in_width_max_5tap_rgb = 1280, 150 151 .in_width_max_3tap_rgb = 2560, ··· 235 246 }; 236 247 237 248 const struct dispc_features dispc_j721e_feats = { 238 - .max_pclk_khz = { 239 - [DISPC_VP_DPI] = 170000, 240 - [DISPC_VP_INTERNAL] = 600000, 241 - }, 242 - 243 249 .scaling = { 244 250 .in_width_max_5tap_rgb = 2048, 245 251 .in_width_max_3tap_rgb = 4096, ··· 301 317 }; 302 318 303 319 const struct dispc_features dispc_am625_feats = { 304 - .max_pclk_khz = { 305 - [DISPC_VP_DPI] = 165000, 306 - [DISPC_VP_INTERNAL] = 170000, 307 - }, 308 - 309 320 .scaling = { 310 321 .in_width_max_5tap_rgb = 1280, 311 322 .in_width_max_3tap_rgb = 2560, ··· 357 378 }; 358 379 359 380 const struct dispc_features dispc_am62a7_feats = { 360 - /* 361 - * if the code reaches dispc_mode_valid with VP1, 362 - * it should return MODE_BAD. 363 - */ 364 - .max_pclk_khz = { 365 - [DISPC_VP_TIED_OFF] = 0, 366 - [DISPC_VP_DPI] = 165000, 367 - }, 368 - 369 381 .scaling = { 370 382 .in_width_max_5tap_rgb = 1280, 371 383 .in_width_max_3tap_rgb = 2560, ··· 413 443 }; 414 444 415 445 const struct dispc_features dispc_am62l_feats = { 416 - .max_pclk_khz = { 417 - [DISPC_VP_DPI] = 165000, 418 - }, 419 - 420 446 .subrev = DISPC_AM62L, 421 447 422 448 .common = "common", ··· 1290 1324 DISPC_OVR_DEFAULT_COLOR2, (v >> 32) & 0xffff); 1291 1325 } 1292 1326 1327 + /* 1328 + * Calculate the percentage difference between the requested pixel clock rate 1329 + * and the effective rate resulting from calculating the clock divider value. 1330 + */ 1331 + unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate) 1332 + { 1333 + int r = rate / 100, rr = real_rate / 100; 1334 + 1335 + return (unsigned int)(abs(((rr - r) * 100) / r)); 1336 + } 1337 + 1338 + static int check_pixel_clock(struct dispc_device *dispc, u32 hw_videoport, 1339 + unsigned long clock) 1340 + { 1341 + unsigned long round_clock; 1342 + 1343 + round_clock = clk_round_rate(dispc->vp_clk[hw_videoport], clock); 1344 + /* 1345 + * To keep the check consistent with dispc_vp_set_clk_rate(), we 1346 + * use the same 5% check here. 1347 + */ 1348 + if (dispc_pclk_diff(clock, round_clock) > 5) 1349 + return -EINVAL; 1350 + 1351 + return 0; 1352 + } 1353 + 1293 1354 enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc, 1294 1355 u32 hw_videoport, 1295 1356 const struct drm_display_mode *mode) 1296 1357 { 1297 1358 u32 hsw, hfp, hbp, vsw, vfp, vbp; 1298 1359 enum dispc_vp_bus_type bus_type; 1299 - int max_pclk; 1300 1360 1301 1361 bus_type = dispc->feat->vp_bus_type[hw_videoport]; 1302 1362 1303 - max_pclk = dispc->feat->max_pclk_khz[bus_type]; 1304 - 1305 - if (WARN_ON(max_pclk == 0)) 1363 + if (WARN_ON(bus_type == DISPC_VP_TIED_OFF)) 1306 1364 return MODE_BAD; 1307 - 1308 - if (mode->clock < dispc->feat->min_pclk_khz) 1309 - return MODE_CLOCK_LOW; 1310 - 1311 - if (mode->clock > max_pclk) 1312 - return MODE_CLOCK_HIGH; 1313 1365 1314 1366 if (mode->hdisplay > 4096) 1315 1367 return MODE_BAD; 1316 1368 1317 1369 if (mode->vdisplay > 4096) 1318 1370 return MODE_BAD; 1371 + 1372 + if (check_pixel_clock(dispc, hw_videoport, mode->clock * 1000)) 1373 + return MODE_CLOCK_RANGE; 1319 1374 1320 1375 /* TODO: add interlace support */ 1321 1376 if (mode->flags & DRM_MODE_FLAG_INTERLACE) ··· 1399 1412 void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport) 1400 1413 { 1401 1414 clk_disable_unprepare(dispc->vp_clk[hw_videoport]); 1402 - } 1403 - 1404 - /* 1405 - * Calculate the percentage difference between the requested pixel clock rate 1406 - * and the effective rate resulting from calculating the clock divider value. 1407 - */ 1408 - unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate) 1409 - { 1410 - int r = rate / 100, rr = real_rate / 100; 1411 - 1412 - return (unsigned int)(abs(((rr - r) * 100) / r)); 1413 1415 } 1414 1416 1415 1417 int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
-3
drivers/gpu/drm/tidss/tidss_dispc.h
··· 77 77 }; 78 78 79 79 struct dispc_features { 80 - int min_pclk_khz; 81 - int max_pclk_khz[DISPC_VP_MAX_BUS_TYPE]; 82 - 83 80 struct dispc_features_scaling scaling; 84 81 85 82 enum dispc_dss_subrevision subrev;