Skip to content

Commit 527e132

Browse files
jayesh-titomba
authored andcommitted
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>
1 parent 54c33a4 commit 527e132

2 files changed

Lines changed: 31 additions & 58 deletions

File tree

drivers/gpu/drm/tidss/tidss_dispc.c

Lines changed: 31 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ static const u16 tidss_k2g_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
5858
};
5959

6060
const struct dispc_features dispc_k2g_feats = {
61-
.min_pclk_khz = 4375,
62-
63-
.max_pclk_khz = {
64-
[DISPC_VP_DPI] = 150000,
65-
},
66-
6761
/*
6862
* XXX According TRM the RGB input buffer width up to 2560 should
6963
* work on 3 taps, but in practice it only works up to 1280.
@@ -146,11 +140,6 @@ static const u16 tidss_am65x_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
146140
};
147141

148142
const struct dispc_features dispc_am65x_feats = {
149-
.max_pclk_khz = {
150-
[DISPC_VP_DPI] = 165000,
151-
[DISPC_VP_OLDI_AM65X] = 165000,
152-
},
153-
154143
.scaling = {
155144
.in_width_max_5tap_rgb = 1280,
156145
.in_width_max_3tap_rgb = 2560,
@@ -246,11 +235,6 @@ static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
246235
};
247236

248237
const struct dispc_features dispc_j721e_feats = {
249-
.max_pclk_khz = {
250-
[DISPC_VP_DPI] = 170000,
251-
[DISPC_VP_INTERNAL] = 600000,
252-
},
253-
254238
.scaling = {
255239
.in_width_max_5tap_rgb = 2048,
256240
.in_width_max_3tap_rgb = 4096,
@@ -317,11 +301,6 @@ const struct dispc_features dispc_j721e_feats = {
317301
};
318302

319303
const struct dispc_features dispc_am625_feats = {
320-
.max_pclk_khz = {
321-
[DISPC_VP_DPI] = 165000,
322-
[DISPC_VP_INTERNAL] = 170000,
323-
},
324-
325304
.scaling = {
326305
.in_width_max_5tap_rgb = 1280,
327306
.in_width_max_3tap_rgb = 2560,
@@ -378,15 +357,6 @@ const struct dispc_features dispc_am625_feats = {
378357
};
379358

380359
const struct dispc_features dispc_am62a7_feats = {
381-
/*
382-
* if the code reaches dispc_mode_valid with VP1,
383-
* it should return MODE_BAD.
384-
*/
385-
.max_pclk_khz = {
386-
[DISPC_VP_TIED_OFF] = 0,
387-
[DISPC_VP_DPI] = 165000,
388-
},
389-
390360
.scaling = {
391361
.in_width_max_5tap_rgb = 1280,
392362
.in_width_max_3tap_rgb = 2560,
@@ -443,10 +413,6 @@ const struct dispc_features dispc_am62a7_feats = {
443413
};
444414

445415
const struct dispc_features dispc_am62l_feats = {
446-
.max_pclk_khz = {
447-
[DISPC_VP_DPI] = 165000,
448-
},
449-
450416
.subrev = DISPC_AM62L,
451417

452418
.common = "common",
@@ -1324,33 +1290,54 @@ static void dispc_vp_set_default_color(struct dispc_device *dispc,
13241290
DISPC_OVR_DEFAULT_COLOR2, (v >> 32) & 0xffff);
13251291
}
13261292

1293+
/*
1294+
* Calculate the percentage difference between the requested pixel clock rate
1295+
* and the effective rate resulting from calculating the clock divider value.
1296+
*/
1297+
unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate)
1298+
{
1299+
int r = rate / 100, rr = real_rate / 100;
1300+
1301+
return (unsigned int)(abs(((rr - r) * 100) / r));
1302+
}
1303+
1304+
static int check_pixel_clock(struct dispc_device *dispc, u32 hw_videoport,
1305+
unsigned long clock)
1306+
{
1307+
unsigned long round_clock;
1308+
1309+
round_clock = clk_round_rate(dispc->vp_clk[hw_videoport], clock);
1310+
/*
1311+
* To keep the check consistent with dispc_vp_set_clk_rate(), we
1312+
* use the same 5% check here.
1313+
*/
1314+
if (dispc_pclk_diff(clock, round_clock) > 5)
1315+
return -EINVAL;
1316+
1317+
return 0;
1318+
}
1319+
13271320
enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc,
13281321
u32 hw_videoport,
13291322
const struct drm_display_mode *mode)
13301323
{
13311324
u32 hsw, hfp, hbp, vsw, vfp, vbp;
13321325
enum dispc_vp_bus_type bus_type;
1333-
int max_pclk;
13341326

13351327
bus_type = dispc->feat->vp_bus_type[hw_videoport];
13361328

1337-
max_pclk = dispc->feat->max_pclk_khz[bus_type];
1338-
1339-
if (WARN_ON(max_pclk == 0))
1329+
if (WARN_ON(bus_type == DISPC_VP_TIED_OFF))
13401330
return MODE_BAD;
13411331

1342-
if (mode->clock < dispc->feat->min_pclk_khz)
1343-
return MODE_CLOCK_LOW;
1344-
1345-
if (mode->clock > max_pclk)
1346-
return MODE_CLOCK_HIGH;
1347-
13481332
if (mode->hdisplay > 4096)
13491333
return MODE_BAD;
13501334

13511335
if (mode->vdisplay > 4096)
13521336
return MODE_BAD;
13531337

1338+
if (check_pixel_clock(dispc, hw_videoport, mode->clock * 1000))
1339+
return MODE_CLOCK_RANGE;
1340+
13541341
/* TODO: add interlace support */
13551342
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
13561343
return MODE_NO_INTERLACE;
@@ -1414,17 +1401,6 @@ void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport)
14141401
clk_disable_unprepare(dispc->vp_clk[hw_videoport]);
14151402
}
14161403

1417-
/*
1418-
* Calculate the percentage difference between the requested pixel clock rate
1419-
* and the effective rate resulting from calculating the clock divider value.
1420-
*/
1421-
unsigned int dispc_pclk_diff(unsigned long rate, unsigned long real_rate)
1422-
{
1423-
int r = rate / 100, rr = real_rate / 100;
1424-
1425-
return (unsigned int)(abs(((rr - r) * 100) / r));
1426-
}
1427-
14281404
int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
14291405
unsigned long rate)
14301406
{

drivers/gpu/drm/tidss/tidss_dispc.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,6 @@ enum dispc_dss_subrevision {
7777
};
7878

7979
struct dispc_features {
80-
int min_pclk_khz;
81-
int max_pclk_khz[DISPC_VP_MAX_BUS_TYPE];
82-
8380
struct dispc_features_scaling scaling;
8481

8582
enum dispc_dss_subrevision subrev;

0 commit comments

Comments
 (0)