* [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
@ 2025-11-01 23:15 Aaron Kling via B4 Relay
2025-11-02 17:03 ` kernel test robot
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Aaron Kling via B4 Relay @ 2025-11-01 23:15 UTC (permalink / raw)
To: Thierry Reding, Mikko Perttunen, David Airlie, Simona Vetter,
Jonathan Hunter
Cc: dri-devel, linux-tegra, linux-kernel, Aaron Kling
From: Aaron Kling <webgeek1234@gmail.com>
Without the cmu, nvdisplay will display colors that are notably darker
than intended. The vendor bootloader and the downstream display driver
enable the cmu and sets a sRGB table. Loading that table here results in
the intended colors.
Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
---
drivers/gpu/drm/tegra/dc.h | 13 +++
drivers/gpu/drm/tegra/sor.c | 206 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 219 insertions(+)
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 0559fa6b1bf70416e51d5067cc04a6ae6572de23..286eddd89a28f7ea9e64c00f03af76f6c68ae9d8 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -447,11 +447,24 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define BASE_COLOR_SIZE_888 ( 8 << 0)
#define BASE_COLOR_SIZE_101010 ( 10 << 0)
#define BASE_COLOR_SIZE_121212 ( 12 << 0)
+#define CMU_ENABLE_MASK (1 << 20)
+#define CMU_ENABLE_DISABLE (0 << 20)
+#define CMU_ENABLE_ENABLE (1 << 20)
#define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
#define SC1_H_QUALIFIER_NONE (1 << 16)
#define SC0_H_QUALIFIER_NONE (1 << 0)
+/* Nvdisplay */
+#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT 0x431
+#define OUTPUT_LUT_MODE_MASK (3 << 5)
+#define OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
+#define OUTPUT_LUT_SIZE_MASK (3 << 1)
+#define OUTPUT_LUT_SIZE_SIZE_1025 (2 << 1)
+
+#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE 0x432
+#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI 0x433
+
#define DC_DISP_DATA_ENABLE_OPTIONS 0x432
#define DE_SELECT_ACTIVE_BLANK (0 << 0)
#define DE_SELECT_ACTIVE (1 << 0)
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 21f3dfdcc5c9576580b9aa9990dd1bedcdeb4482..a381cb35113c0f3191d7204302f4024f33141622 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -443,6 +443,9 @@ struct tegra_sor {
bool scdc_enabled;
struct tegra_hda_format format;
+
+ u64 *cmu_output_lut;
+ dma_addr_t cmu_output_phys;
};
struct tegra_sor_state {
@@ -483,6 +486,180 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output)
return container_of(output, struct tegra_sor, output);
}
+static u16 default_srgb_lut[] = {
+ 0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4,
+ 0x6469, 0x64F0, 0x656B, 0x65DF, 0x664A, 0x66B0,
+ 0x6711, 0x676D, 0x67C4, 0x6819, 0x686A, 0x68B8,
+ 0x6904, 0x694D, 0x6994, 0x69D8, 0x6A1B, 0x6A5D,
+ 0x6A9C, 0x6ADA, 0x6B17, 0x6B52, 0x6B8C, 0x6BC5,
+ 0x6BFD, 0x6C33, 0x6C69, 0x6C9E, 0x6CD1, 0x6D04,
+ 0x6D36, 0x6D67, 0x6D98, 0x6DC7, 0x6DF6, 0x6E25,
+ 0x6E52, 0x6E7F, 0x6EAC, 0x6ED7, 0x6F03, 0x6F2D,
+ 0x6F58, 0x6F81, 0x6FAA, 0x6FD3, 0x6FFB, 0x7023,
+ 0x704B, 0x7071, 0x7098, 0x70BE, 0x70E4, 0x7109,
+ 0x712E, 0x7153, 0x7177, 0x719B, 0x71BF, 0x71E2,
+ 0x7205, 0x7227, 0x724A, 0x726C, 0x728E, 0x72AF,
+ 0x72D0, 0x72F1, 0x7312, 0x7333, 0x7353, 0x7373,
+ 0x7392, 0x73B2, 0x73D1, 0x73F0, 0x740F, 0x742D,
+ 0x744C, 0x746A, 0x7488, 0x74A6, 0x74C3, 0x74E0,
+ 0x74FE, 0x751B, 0x7537, 0x7554, 0x7570, 0x758D,
+ 0x75A9, 0x75C4, 0x75E0, 0x75FC, 0x7617, 0x7632,
+ 0x764D, 0x7668, 0x7683, 0x769E, 0x76B8, 0x76D3,
+ 0x76ED, 0x7707, 0x7721, 0x773B, 0x7754, 0x776E,
+ 0x7787, 0x77A0, 0x77B9, 0x77D2, 0x77EB, 0x7804,
+ 0x781D, 0x7835, 0x784E, 0x7866, 0x787E, 0x7896,
+ 0x78AE, 0x78C6, 0x78DD, 0x78F5, 0x790D, 0x7924,
+ 0x793B, 0x7952, 0x796A, 0x7981, 0x7997, 0x79AE,
+ 0x79C5, 0x79DB, 0x79F2, 0x7A08, 0x7A1F, 0x7A35,
+ 0x7A4B, 0x7A61, 0x7A77, 0x7A8D, 0x7AA3, 0x7AB8,
+ 0x7ACE, 0x7AE3, 0x7AF9, 0x7B0E, 0x7B24, 0x7B39,
+ 0x7B4E, 0x7B63, 0x7B78, 0x7B8D, 0x7BA2, 0x7BB6,
+ 0x7BCB, 0x7BE0, 0x7BF4, 0x7C08, 0x7C1D, 0x7C31,
+ 0x7C45, 0x7C59, 0x7C6E, 0x7C82, 0x7C96, 0x7CA9,
+ 0x7CBD, 0x7CD1, 0x7CE5, 0x7CF8, 0x7D0C, 0x7D1F,
+ 0x7D33, 0x7D46, 0x7D59, 0x7D6D, 0x7D80, 0x7D93,
+ 0x7DA6, 0x7DB9, 0x7DCC, 0x7DDF, 0x7DF2, 0x7E04,
+ 0x7E17, 0x7E2A, 0x7E3C, 0x7E4F, 0x7E61, 0x7E74,
+ 0x7E86, 0x7E98, 0x7EAB, 0x7EBD, 0x7ECF, 0x7EE1,
+ 0x7EF3, 0x7F05, 0x7F17, 0x7F29, 0x7F3B, 0x7F4D,
+ 0x7F5E, 0x7F70, 0x7F82, 0x7F93, 0x7FA5, 0x7FB6,
+ 0x7FC8, 0x7FD9, 0x7FEB, 0x7FFC, 0x800D, 0x801E,
+ 0x8030, 0x8041, 0x8052, 0x8063, 0x8074, 0x8085,
+ 0x8096, 0x80A7, 0x80B7, 0x80C8, 0x80D9, 0x80EA,
+ 0x80FA, 0x810B, 0x811C, 0x812C, 0x813D, 0x814D,
+ 0x815D, 0x816E, 0x817E, 0x818E, 0x819F, 0x81AF,
+ 0x81BF, 0x81CF, 0x81DF, 0x81EF, 0x81FF, 0x820F,
+ 0x821F, 0x822F, 0x823F, 0x824F, 0x825F, 0x826F,
+ 0x827E, 0x828E, 0x829E, 0x82AD, 0x82BD, 0x82CC,
+ 0x82DC, 0x82EB, 0x82FB, 0x830A, 0x831A, 0x8329,
+ 0x8338, 0x8348, 0x8357, 0x8366, 0x8375, 0x8385,
+ 0x8394, 0x83A3, 0x83B2, 0x83C1, 0x83D0, 0x83DF,
+ 0x83EE, 0x83FD, 0x840C, 0x841A, 0x8429, 0x8438,
+ 0x8447, 0x8455, 0x8464, 0x8473, 0x8481, 0x8490,
+ 0x849F, 0x84AD, 0x84BC, 0x84CA, 0x84D9, 0x84E7,
+ 0x84F5, 0x8504, 0x8512, 0x8521, 0x852F, 0x853D,
+ 0x854B, 0x855A, 0x8568, 0x8576, 0x8584, 0x8592,
+ 0x85A0, 0x85AE, 0x85BC, 0x85CA, 0x85D8, 0x85E6,
+ 0x85F4, 0x8602, 0x8610, 0x861E, 0x862C, 0x8639,
+ 0x8647, 0x8655, 0x8663, 0x8670, 0x867E, 0x868C,
+ 0x8699, 0x86A7, 0x86B5, 0x86C2, 0x86D0, 0x86DD,
+ 0x86EB, 0x86F8, 0x8705, 0x8713, 0x8720, 0x872E,
+ 0x873B, 0x8748, 0x8756, 0x8763, 0x8770, 0x877D,
+ 0x878B, 0x8798, 0x87A5, 0x87B2, 0x87BF, 0x87CC,
+ 0x87D9, 0x87E6, 0x87F3, 0x8801, 0x880E, 0x881A,
+ 0x8827, 0x8834, 0x8841, 0x884E, 0x885B, 0x8868,
+ 0x8875, 0x8882, 0x888E, 0x889B, 0x88A8, 0x88B5,
+ 0x88C1, 0x88CE, 0x88DB, 0x88E7, 0x88F4, 0x8900,
+ 0x890D, 0x891A, 0x8926, 0x8933, 0x893F, 0x894C,
+ 0x8958, 0x8965, 0x8971, 0x897D, 0x898A, 0x8996,
+ 0x89A3, 0x89AF, 0x89BB, 0x89C8, 0x89D4, 0x89E0,
+ 0x89EC, 0x89F9, 0x8A05, 0x8A11, 0x8A1D, 0x8A29,
+ 0x8A36, 0x8A42, 0x8A4E, 0x8A5A, 0x8A66, 0x8A72,
+ 0x8A7E, 0x8A8A, 0x8A96, 0x8AA2, 0x8AAE, 0x8ABA,
+ 0x8AC6, 0x8AD2, 0x8ADE, 0x8AEA, 0x8AF5, 0x8B01,
+ 0x8B0D, 0x8B19, 0x8B25, 0x8B31, 0x8B3C, 0x8B48,
+ 0x8B54, 0x8B60, 0x8B6B, 0x8B77, 0x8B83, 0x8B8E,
+ 0x8B9A, 0x8BA6, 0x8BB1, 0x8BBD, 0x8BC8, 0x8BD4,
+ 0x8BDF, 0x8BEB, 0x8BF6, 0x8C02, 0x8C0D, 0x8C19,
+ 0x8C24, 0x8C30, 0x8C3B, 0x8C47, 0x8C52, 0x8C5D,
+ 0x8C69, 0x8C74, 0x8C80, 0x8C8B, 0x8C96, 0x8CA1,
+ 0x8CAD, 0x8CB8, 0x8CC3, 0x8CCF, 0x8CDA, 0x8CE5,
+ 0x8CF0, 0x8CFB, 0x8D06, 0x8D12, 0x8D1D, 0x8D28,
+ 0x8D33, 0x8D3E, 0x8D49, 0x8D54, 0x8D5F, 0x8D6A,
+ 0x8D75, 0x8D80, 0x8D8B, 0x8D96, 0x8DA1, 0x8DAC,
+ 0x8DB7, 0x8DC2, 0x8DCD, 0x8DD8, 0x8DE3, 0x8DEE,
+ 0x8DF9, 0x8E04, 0x8E0E, 0x8E19, 0x8E24, 0x8E2F,
+ 0x8E3A, 0x8E44, 0x8E4F, 0x8E5A, 0x8E65, 0x8E6F,
+ 0x8E7A, 0x8E85, 0x8E90, 0x8E9A, 0x8EA5, 0x8EB0,
+ 0x8EBA, 0x8EC5, 0x8ECF, 0x8EDA, 0x8EE5, 0x8EEF,
+ 0x8EFA, 0x8F04, 0x8F0F, 0x8F19, 0x8F24, 0x8F2E,
+ 0x8F39, 0x8F43, 0x8F4E, 0x8F58, 0x8F63, 0x8F6D,
+ 0x8F78, 0x8F82, 0x8F8C, 0x8F97, 0x8FA1, 0x8FAC,
+ 0x8FB6, 0x8FC0, 0x8FCB, 0x8FD5, 0x8FDF, 0x8FEA,
+ 0x8FF4, 0x8FFE, 0x9008, 0x9013, 0x901D, 0x9027,
+ 0x9031, 0x903C, 0x9046, 0x9050, 0x905A, 0x9064,
+ 0x906E, 0x9079, 0x9083, 0x908D, 0x9097, 0x90A1,
+ 0x90AB, 0x90B5, 0x90BF, 0x90C9, 0x90D3, 0x90DD,
+ 0x90E7, 0x90F1, 0x90FB, 0x9105, 0x910F, 0x9119,
+ 0x9123, 0x912D, 0x9137, 0x9141, 0x914B, 0x9155,
+ 0x915F, 0x9169, 0x9173, 0x917D, 0x9186, 0x9190,
+ 0x919A, 0x91A4, 0x91AE, 0x91B8, 0x91C1, 0x91CB,
+ 0x91D5, 0x91DF, 0x91E9, 0x91F2, 0x91FC, 0x9206,
+ 0x9210, 0x9219, 0x9223, 0x922D, 0x9236, 0x9240,
+ 0x924A, 0x9253, 0x925D, 0x9267, 0x9270, 0x927A,
+ 0x9283, 0x928D, 0x9297, 0x92A0, 0x92AA, 0x92B3,
+ 0x92BD, 0x92C6, 0x92D0, 0x92DA, 0x92E3, 0x92ED,
+ 0x92F6, 0x9300, 0x9309, 0x9313, 0x931C, 0x9325,
+ 0x932F, 0x9338, 0x9342, 0x934B, 0x9355, 0x935E,
+ 0x9367, 0x9371, 0x937A, 0x9384, 0x938D, 0x9396,
+ 0x93A0, 0x93A9, 0x93B2, 0x93BC, 0x93C5, 0x93CE,
+ 0x93D7, 0x93E1, 0x93EA, 0x93F3, 0x93FC, 0x9406,
+ 0x940F, 0x9418, 0x9421, 0x942B, 0x9434, 0x943D,
+ 0x9446, 0x944F, 0x9459, 0x9462, 0x946B, 0x9474,
+ 0x947D, 0x9486, 0x948F, 0x9499, 0x94A2, 0x94AB,
+ 0x94B4, 0x94BD, 0x94C6, 0x94CF, 0x94D8, 0x94E1,
+ 0x94EA, 0x94F3, 0x94FC, 0x9505, 0x950E, 0x9517,
+ 0x9520, 0x9529, 0x9532, 0x953B, 0x9544, 0x954D,
+ 0x9556, 0x955F, 0x9568, 0x9571, 0x957A, 0x9583,
+ 0x958C, 0x9595, 0x959D, 0x95A6, 0x95AF, 0x95B8,
+ 0x95C1, 0x95CA, 0x95D3, 0x95DB, 0x95E4, 0x95ED,
+ 0x95F6, 0x95FF, 0x9608, 0x9610, 0x9619, 0x9622,
+ 0x962B, 0x9633, 0x963C, 0x9645, 0x964E, 0x9656,
+ 0x965F, 0x9668, 0x9671, 0x9679, 0x9682, 0x968B,
+ 0x9693, 0x969C, 0x96A5, 0x96AD, 0x96B6, 0x96BF,
+ 0x96C7, 0x96D0, 0x96D9, 0x96E1, 0x96EA, 0x96F2,
+ 0x96FB, 0x9704, 0x970C, 0x9715, 0x971D, 0x9726,
+ 0x972E, 0x9737, 0x9740, 0x9748, 0x9751, 0x9759,
+ 0x9762, 0x976A, 0x9773, 0x977B, 0x9784, 0x978C,
+ 0x9795, 0x979D, 0x97A6, 0x97AE, 0x97B6, 0x97BF,
+ 0x97C7, 0x97D0, 0x97D8, 0x97E1, 0x97E9, 0x97F1,
+ 0x97FA, 0x9802, 0x980B, 0x9813, 0x981B, 0x9824,
+ 0x982C, 0x9834, 0x983D, 0x9845, 0x984D, 0x9856,
+ 0x985E, 0x9866, 0x986F, 0x9877, 0x987F, 0x9888,
+ 0x9890, 0x9898, 0x98A0, 0x98A9, 0x98B1, 0x98B9,
+ 0x98C1, 0x98CA, 0x98D2, 0x98DA, 0x98E2, 0x98EB,
+ 0x98F3, 0x98FB, 0x9903, 0x990B, 0x9914, 0x991C,
+ 0x9924, 0x992C, 0x9934, 0x993C, 0x9945, 0x994D,
+ 0x9955, 0x995D, 0x9965, 0x996D, 0x9975, 0x997D,
+ 0x9986, 0x998E, 0x9996, 0x999E, 0x99A6, 0x99AE,
+ 0x99B6, 0x99BE, 0x99C6, 0x99CE, 0x99D6, 0x99DE,
+ 0x99E6, 0x99EE, 0x99F6, 0x99FE, 0x9A06, 0x9A0E,
+ 0x9A16, 0x9A1E, 0x9A26, 0x9A2E, 0x9A36, 0x9A3E,
+ 0x9A46, 0x9A4E, 0x9A56, 0x9A5E, 0x9A66, 0x9A6E,
+ 0x9A76, 0x9A7E, 0x9A86, 0x9A8E, 0x9A96, 0x9A9D,
+ 0x9AA5, 0x9AAD, 0x9AB5, 0x9ABD, 0x9AC5, 0x9ACD,
+ 0x9AD5, 0x9ADC, 0x9AE4, 0x9AEC, 0x9AF4, 0x9AFC,
+ 0x9B04, 0x9B0C, 0x9B13, 0x9B1B, 0x9B23, 0x9B2B,
+ 0x9B33, 0x9B3A, 0x9B42, 0x9B4A, 0x9B52, 0x9B59,
+ 0x9B61, 0x9B69, 0x9B71, 0x9B79, 0x9B80, 0x9B88,
+ 0x9B90, 0x9B97, 0x9B9F, 0x9BA7, 0x9BAF, 0x9BB6,
+ 0x9BBE, 0x9BC6, 0x9BCD, 0x9BD5, 0x9BDD, 0x9BE5,
+ 0x9BEC, 0x9BF4, 0x9BFC, 0x9C03, 0x9C0B, 0x9C12,
+ 0x9C1A, 0x9C22, 0x9C29, 0x9C31, 0x9C39, 0x9C40,
+ 0x9C48, 0x9C50, 0x9C57, 0x9C5F, 0x9C66, 0x9C6E,
+ 0x9C75, 0x9C7D, 0x9C85, 0x9C8C, 0x9C94, 0x9C9B,
+ 0x9CA3, 0x9CAA, 0x9CB2, 0x9CBA, 0x9CC1, 0x9CC9,
+ 0x9CD0, 0x9CD8, 0x9CDF, 0x9CE7, 0x9CEE, 0x9CF6,
+ 0x9CFD, 0x9D05, 0x9D0C, 0x9D14, 0x9D1B, 0x9D23,
+ 0x9D2A, 0x9D32, 0x9D39, 0x9D40, 0x9D48, 0x9D4F,
+ 0x9D57, 0x9D5E, 0x9D66, 0x9D6D, 0x9D75, 0x9D7C,
+ 0x9D83, 0x9D8B, 0x9D92, 0x9D9A, 0x9DA1, 0x9DA8,
+ 0x9DB0, 0x9DB7, 0x9DBE, 0x9DC6, 0x9DCD, 0x9DD5,
+ 0x9DDC, 0x9DE3, 0x9DEB, 0x9DF2, 0x9DF9, 0x9E01,
+ 0x9E08, 0x9E0F, 0x9E17, 0x9E1E, 0x9E25, 0x9E2D,
+ 0x9E34, 0x9E3B, 0x9E43, 0x9E4A, 0x9E51, 0x9E58,
+ 0x9E60, 0x9E67, 0x9E6E, 0x9E75, 0x9E7D, 0x9E84,
+ 0x9E8B, 0x9E92, 0x9E9A, 0x9EA1, 0x9EA8, 0x9EAF,
+ 0x9EB7, 0x9EBE, 0x9EC5, 0x9ECC, 0x9ED4, 0x9EDB,
+ 0x9EE2, 0x9EE9, 0x9EF0, 0x9EF7, 0x9EFF, 0x9F06,
+ 0x9F0D, 0x9F14, 0x9F1B, 0x9F23, 0x9F2A, 0x9F31,
+ 0x9F38, 0x9F3F, 0x9F46, 0x9F4D, 0x9F55, 0x9F5C,
+ 0x9F63, 0x9F6A, 0x9F71, 0x9F78, 0x9F7F, 0x9F86,
+ 0x9F8D, 0x9F95, 0x9F9C, 0x9FA3, 0x9FAA, 0x9FB1,
+ 0x9FB8, 0x9FBF, 0x9FC6, 0x9FCD, 0x9FD4, 0x9FDB,
+ 0x9FE2, 0x9FE9, 0x9FF0, 0x9FF7, 0x9FFF,
+};
+
static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset)
{
u32 value = readl(sor->regs + (offset << 2));
@@ -2241,6 +2418,13 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
host1x_client_suspend(&sor->client);
+
+ if (sor->soc->has_nvdisplay) {
+ dma_free_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
+ sor->cmu_output_lut, sor->cmu_output_phys);
+ sor->cmu_output_lut = NULL;
+ sor->cmu_output_phys = 0;
+ }
}
static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
@@ -2255,6 +2439,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
unsigned long rate, pclk;
unsigned int div, i;
u32 value;
+ u64 r;
int err;
state = to_sor_state(output->connector.state);
@@ -2557,6 +2742,27 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
value &= ~DITHER_CONTROL_MASK;
value &= ~BASE_COLOR_SIZE_MASK;
+ if (dc->soc->has_nvdisplay) {
+ sor->cmu_output_lut =
+ dma_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
+ &sor->cmu_output_phys, GFP_KERNEL);
+
+ for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
+ r = default_srgb_lut[i];
+ sor->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
+ }
+
+ tegra_dc_writel(dc, (u32)(sor->cmu_output_phys & 0xffffffff),
+ DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
+ tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
+ DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
+
+ tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
+ DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
+
+ value |= CMU_ENABLE_ENABLE;
+ }
+
switch (state->bpc) {
case 6:
value |= BASE_COLOR_SIZE_666;
---
base-commit: dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa
change-id: 20251031-tegra-drm-cmu-697e8e030978
Best regards,
--
Aaron Kling <webgeek1234@gmail.com>
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-01 23:15 [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194 Aaron Kling via B4 Relay
@ 2025-11-02 17:03 ` kernel test robot
2025-11-02 17:44 ` kernel test robot
2025-11-03 11:54 ` Thierry Reding
2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-11-02 17:03 UTC (permalink / raw)
To: Aaron Kling via B4 Relay, Thierry Reding, Mikko Perttunen,
David Airlie, Simona Vetter, Jonathan Hunter
Cc: oe-kbuild-all, dri-devel, linux-tegra, linux-kernel, Aaron Kling
Hi Aaron,
kernel test robot noticed the following build warnings:
[auto build test WARNING on dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa]
url: https://github.com/intel-lab-lkp/linux/commits/Aaron-Kling-via-B4-Relay/drm-tegra-Enable-cmu-for-Tegra186-and-Tegra194/20251102-071726
base: dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa
patch link: https://lore.kernel.org/r/20251101-tegra-drm-cmu-v1-1-211799755ab8%40gmail.com
patch subject: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
config: arm-randconfig-002-20251102 (https://download.01.org/0day-ci/archive/20251103/202511030007.5ksWfboC-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 10.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251103/202511030007.5ksWfboC-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511030007.5ksWfboC-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/gpu/drm/tegra/sor.c: In function 'tegra_sor_hdmi_enable':
>> drivers/gpu/drm/tegra/sor.c:2757:50: warning: right shift count >= width of type [-Wshift-count-overflow]
2757 | tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
| ^~
vim +2757 drivers/gpu/drm/tegra/sor.c
2590
2591 /* switch the SOR clock to the pad clock */
2592 err = tegra_sor_set_parent_clock(sor, sor->clk_pad);
2593 if (err < 0) {
2594 dev_err(sor->dev, "failed to select SOR parent clock: %d\n",
2595 err);
2596 return;
2597 }
2598
2599 /* switch the output clock to the parent pixel clock */
2600 err = clk_set_parent(sor->clk, sor->clk_parent);
2601 if (err < 0) {
2602 dev_err(sor->dev, "failed to select output parent clock: %d\n",
2603 err);
2604 return;
2605 }
2606
2607 /* adjust clock rate for HDMI 2.0 modes */
2608 rate = clk_get_rate(sor->clk_parent);
2609
2610 if (mode->clock >= 340000)
2611 rate /= 2;
2612
2613 DRM_DEBUG_KMS("setting clock to %lu Hz, mode: %lu Hz\n", rate, pclk);
2614
2615 clk_set_rate(sor->clk, rate);
2616
2617 if (!sor->soc->has_nvdisplay) {
2618 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
2619
2620 /* XXX is this the proper check? */
2621 if (mode->clock < 75000)
2622 value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED;
2623
2624 tegra_sor_writel(sor, value, SOR_INPUT_CONTROL);
2625 }
2626
2627 max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32;
2628
2629 value = SOR_HDMI_CTRL_ENABLE | SOR_HDMI_CTRL_MAX_AC_PACKET(max_ac) |
2630 SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY);
2631 tegra_sor_writel(sor, value, SOR_HDMI_CTRL);
2632
2633 if (!dc->soc->has_nvdisplay) {
2634 /* H_PULSE2 setup */
2635 pulse_start = h_ref_to_sync +
2636 (mode->hsync_end - mode->hsync_start) +
2637 (mode->htotal - mode->hsync_end) - 10;
2638
2639 value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE |
2640 PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL;
2641 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
2642
2643 value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start);
2644 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
2645
2646 value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0);
2647 value |= H_PULSE2_ENABLE;
2648 tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0);
2649 }
2650
2651 /* infoframe setup */
2652 err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode);
2653 if (err < 0)
2654 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
2655
2656 /* XXX HDMI audio support not implemented yet */
2657 tegra_sor_hdmi_disable_audio_infoframe(sor);
2658
2659 /* use single TMDS protocol */
2660 value = tegra_sor_readl(sor, SOR_STATE1);
2661 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
2662 value |= SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A;
2663 tegra_sor_writel(sor, value, SOR_STATE1);
2664
2665 /* power up pad calibration */
2666 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2667 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
2668 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2669
2670 /* production settings */
2671 settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
2672 if (!settings) {
2673 dev_err(sor->dev, "no settings for pixel clock %d Hz\n",
2674 mode->clock * 1000);
2675 return;
2676 }
2677
2678 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
2679 value &= ~SOR_PLL0_ICHPMP_MASK;
2680 value &= ~SOR_PLL0_FILTER_MASK;
2681 value &= ~SOR_PLL0_VCOCAP_MASK;
2682 value |= SOR_PLL0_ICHPMP(settings->ichpmp);
2683 value |= SOR_PLL0_FILTER(settings->filter);
2684 value |= SOR_PLL0_VCOCAP(settings->vcocap);
2685 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
2686
2687 /* XXX not in TRM */
2688 value = tegra_sor_readl(sor, sor->soc->regs->pll1);
2689 value &= ~SOR_PLL1_LOADADJ_MASK;
2690 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
2691 value |= SOR_PLL1_LOADADJ(settings->loadadj);
2692 value |= SOR_PLL1_TMDS_TERMADJ(settings->tmds_termadj);
2693 value |= SOR_PLL1_TMDS_TERM;
2694 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
2695
2696 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
2697 value &= ~SOR_PLL3_BG_TEMP_COEF_MASK;
2698 value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK;
2699 value &= ~SOR_PLL3_AVDD10_LEVEL_MASK;
2700 value &= ~SOR_PLL3_AVDD14_LEVEL_MASK;
2701 value |= SOR_PLL3_BG_TEMP_COEF(settings->bg_temp_coef);
2702 value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref_level);
2703 value |= SOR_PLL3_AVDD10_LEVEL(settings->avdd10_level);
2704 value |= SOR_PLL3_AVDD14_LEVEL(settings->avdd14_level);
2705 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
2706
2707 value = settings->drive_current[3] << 24 |
2708 settings->drive_current[2] << 16 |
2709 settings->drive_current[1] << 8 |
2710 settings->drive_current[0] << 0;
2711 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
2712
2713 value = settings->preemphasis[3] << 24 |
2714 settings->preemphasis[2] << 16 |
2715 settings->preemphasis[1] << 8 |
2716 settings->preemphasis[0] << 0;
2717 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
2718
2719 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2720 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
2721 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
2722 value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu_value);
2723 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2724
2725 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl2);
2726 value &= ~SOR_DP_PADCTL_SPAREPLL_MASK;
2727 value |= SOR_DP_PADCTL_SPAREPLL(settings->sparepll);
2728 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl2);
2729
2730 /* power down pad calibration */
2731 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2732 value |= SOR_DP_PADCTL_PAD_CAL_PD;
2733 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2734
2735 if (!dc->soc->has_nvdisplay) {
2736 /* miscellaneous display controller settings */
2737 value = VSYNC_H_POSITION(1);
2738 tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS);
2739 }
2740
2741 value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
2742 value &= ~DITHER_CONTROL_MASK;
2743 value &= ~BASE_COLOR_SIZE_MASK;
2744
2745 if (dc->soc->has_nvdisplay) {
2746 sor->cmu_output_lut =
2747 dma_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
2748 &sor->cmu_output_phys, GFP_KERNEL);
2749
2750 for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
2751 r = default_srgb_lut[i];
2752 sor->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
2753 }
2754
2755 tegra_dc_writel(dc, (u32)(sor->cmu_output_phys & 0xffffffff),
2756 DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
> 2757 tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
2758 DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
2759
2760 tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
2761 DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
2762
2763 value |= CMU_ENABLE_ENABLE;
2764 }
2765
2766 switch (state->bpc) {
2767 case 6:
2768 value |= BASE_COLOR_SIZE_666;
2769 break;
2770
2771 case 8:
2772 value |= BASE_COLOR_SIZE_888;
2773 break;
2774
2775 case 10:
2776 value |= BASE_COLOR_SIZE_101010;
2777 break;
2778
2779 case 12:
2780 value |= BASE_COLOR_SIZE_121212;
2781 break;
2782
2783 default:
2784 WARN(1, "%u bits-per-color not supported\n", state->bpc);
2785 value |= BASE_COLOR_SIZE_888;
2786 break;
2787 }
2788
2789 tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
2790
2791 /* XXX set display head owner */
2792 value = tegra_sor_readl(sor, SOR_STATE1);
2793 value &= ~SOR_STATE_ASY_OWNER_MASK;
2794 value |= SOR_STATE_ASY_OWNER(1 + dc->pipe);
2795 tegra_sor_writel(sor, value, SOR_STATE1);
2796
2797 err = tegra_sor_power_up(sor, 250);
2798 if (err < 0)
2799 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
2800
2801 /* configure dynamic range of output */
2802 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
2803 value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK;
2804 value &= ~SOR_HEAD_STATE_DYNRANGE_MASK;
2805 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
2806
2807 /* configure colorspace */
2808 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
2809 value &= ~SOR_HEAD_STATE_COLORSPACE_MASK;
2810 value |= SOR_HEAD_STATE_COLORSPACE_RGB;
2811 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
2812
2813 tegra_sor_mode_set(sor, mode, state);
2814
2815 tegra_sor_update(sor);
2816
2817 /* program preamble timing in SOR (XXX) */
2818 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
2819 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
2820 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2821
2822 err = tegra_sor_attach(sor);
2823 if (err < 0)
2824 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
2825
2826 /* enable display to SOR clock and generate HDMI preamble */
2827 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
2828
2829 if (!sor->soc->has_nvdisplay)
2830 value |= SOR1_TIMING_CYA;
2831
2832 value |= SOR_ENABLE(sor->index);
2833
2834 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2835
2836 if (dc->soc->has_nvdisplay) {
2837 value = tegra_dc_readl(dc, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2838 value &= ~PROTOCOL_MASK;
2839 value |= PROTOCOL_SINGLE_TMDS_A;
2840 tegra_dc_writel(dc, value, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2841 }
2842
2843 tegra_dc_commit(dc);
2844
2845 err = tegra_sor_wakeup(sor);
2846 if (err < 0)
2847 dev_err(sor->dev, "failed to wakeup SOR: %d\n", err);
2848
2849 tegra_sor_hdmi_scdc_start(sor);
2850 tegra_sor_audio_prepare(sor);
2851 }
2852
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-01 23:15 [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194 Aaron Kling via B4 Relay
2025-11-02 17:03 ` kernel test robot
@ 2025-11-02 17:44 ` kernel test robot
2025-11-03 11:54 ` Thierry Reding
2 siblings, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-11-02 17:44 UTC (permalink / raw)
To: Aaron Kling via B4 Relay, Thierry Reding, Mikko Perttunen,
David Airlie, Simona Vetter, Jonathan Hunter
Cc: llvm, oe-kbuild-all, dri-devel, linux-tegra, linux-kernel,
Aaron Kling
Hi Aaron,
kernel test robot noticed the following build warnings:
[auto build test WARNING on dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa]
url: https://github.com/intel-lab-lkp/linux/commits/Aaron-Kling-via-B4-Relay/drm-tegra-Enable-cmu-for-Tegra186-and-Tegra194/20251102-071726
base: dcb6fa37fd7bc9c3d2b066329b0d27dedf8becaa
patch link: https://lore.kernel.org/r/20251101-tegra-drm-cmu-v1-1-211799755ab8%40gmail.com
patch subject: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
config: arm-defconfig (https://download.01.org/0day-ci/archive/20251103/202511030131.AADiEKfQ-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project d2625a438020ad35330cda29c3def102c1687b1b)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251103/202511030131.AADiEKfQ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511030131.AADiEKfQ-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/gpu/drm/tegra/sor.c:2757:50: warning: shift count >= width of type [-Wshift-count-overflow]
2757 | tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
| ^ ~~
1 warning generated.
vim +2757 drivers/gpu/drm/tegra/sor.c
2590
2591 /* switch the SOR clock to the pad clock */
2592 err = tegra_sor_set_parent_clock(sor, sor->clk_pad);
2593 if (err < 0) {
2594 dev_err(sor->dev, "failed to select SOR parent clock: %d\n",
2595 err);
2596 return;
2597 }
2598
2599 /* switch the output clock to the parent pixel clock */
2600 err = clk_set_parent(sor->clk, sor->clk_parent);
2601 if (err < 0) {
2602 dev_err(sor->dev, "failed to select output parent clock: %d\n",
2603 err);
2604 return;
2605 }
2606
2607 /* adjust clock rate for HDMI 2.0 modes */
2608 rate = clk_get_rate(sor->clk_parent);
2609
2610 if (mode->clock >= 340000)
2611 rate /= 2;
2612
2613 DRM_DEBUG_KMS("setting clock to %lu Hz, mode: %lu Hz\n", rate, pclk);
2614
2615 clk_set_rate(sor->clk, rate);
2616
2617 if (!sor->soc->has_nvdisplay) {
2618 value = SOR_INPUT_CONTROL_HDMI_SRC_SELECT(dc->pipe);
2619
2620 /* XXX is this the proper check? */
2621 if (mode->clock < 75000)
2622 value |= SOR_INPUT_CONTROL_ARM_VIDEO_RANGE_LIMITED;
2623
2624 tegra_sor_writel(sor, value, SOR_INPUT_CONTROL);
2625 }
2626
2627 max_ac = ((mode->htotal - mode->hdisplay) - SOR_REKEY - 18) / 32;
2628
2629 value = SOR_HDMI_CTRL_ENABLE | SOR_HDMI_CTRL_MAX_AC_PACKET(max_ac) |
2630 SOR_HDMI_CTRL_AUDIO_LAYOUT | SOR_HDMI_CTRL_REKEY(SOR_REKEY);
2631 tegra_sor_writel(sor, value, SOR_HDMI_CTRL);
2632
2633 if (!dc->soc->has_nvdisplay) {
2634 /* H_PULSE2 setup */
2635 pulse_start = h_ref_to_sync +
2636 (mode->hsync_end - mode->hsync_start) +
2637 (mode->htotal - mode->hsync_end) - 10;
2638
2639 value = PULSE_LAST_END_A | PULSE_QUAL_VACTIVE |
2640 PULSE_POLARITY_HIGH | PULSE_MODE_NORMAL;
2641 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_CONTROL);
2642
2643 value = PULSE_END(pulse_start + 8) | PULSE_START(pulse_start);
2644 tegra_dc_writel(dc, value, DC_DISP_H_PULSE2_POSITION_A);
2645
2646 value = tegra_dc_readl(dc, DC_DISP_DISP_SIGNAL_OPTIONS0);
2647 value |= H_PULSE2_ENABLE;
2648 tegra_dc_writel(dc, value, DC_DISP_DISP_SIGNAL_OPTIONS0);
2649 }
2650
2651 /* infoframe setup */
2652 err = tegra_sor_hdmi_setup_avi_infoframe(sor, mode);
2653 if (err < 0)
2654 dev_err(sor->dev, "failed to setup AVI infoframe: %d\n", err);
2655
2656 /* XXX HDMI audio support not implemented yet */
2657 tegra_sor_hdmi_disable_audio_infoframe(sor);
2658
2659 /* use single TMDS protocol */
2660 value = tegra_sor_readl(sor, SOR_STATE1);
2661 value &= ~SOR_STATE_ASY_PROTOCOL_MASK;
2662 value |= SOR_STATE_ASY_PROTOCOL_SINGLE_TMDS_A;
2663 tegra_sor_writel(sor, value, SOR_STATE1);
2664
2665 /* power up pad calibration */
2666 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2667 value &= ~SOR_DP_PADCTL_PAD_CAL_PD;
2668 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2669
2670 /* production settings */
2671 settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
2672 if (!settings) {
2673 dev_err(sor->dev, "no settings for pixel clock %d Hz\n",
2674 mode->clock * 1000);
2675 return;
2676 }
2677
2678 value = tegra_sor_readl(sor, sor->soc->regs->pll0);
2679 value &= ~SOR_PLL0_ICHPMP_MASK;
2680 value &= ~SOR_PLL0_FILTER_MASK;
2681 value &= ~SOR_PLL0_VCOCAP_MASK;
2682 value |= SOR_PLL0_ICHPMP(settings->ichpmp);
2683 value |= SOR_PLL0_FILTER(settings->filter);
2684 value |= SOR_PLL0_VCOCAP(settings->vcocap);
2685 tegra_sor_writel(sor, value, sor->soc->regs->pll0);
2686
2687 /* XXX not in TRM */
2688 value = tegra_sor_readl(sor, sor->soc->regs->pll1);
2689 value &= ~SOR_PLL1_LOADADJ_MASK;
2690 value &= ~SOR_PLL1_TMDS_TERMADJ_MASK;
2691 value |= SOR_PLL1_LOADADJ(settings->loadadj);
2692 value |= SOR_PLL1_TMDS_TERMADJ(settings->tmds_termadj);
2693 value |= SOR_PLL1_TMDS_TERM;
2694 tegra_sor_writel(sor, value, sor->soc->regs->pll1);
2695
2696 value = tegra_sor_readl(sor, sor->soc->regs->pll3);
2697 value &= ~SOR_PLL3_BG_TEMP_COEF_MASK;
2698 value &= ~SOR_PLL3_BG_VREF_LEVEL_MASK;
2699 value &= ~SOR_PLL3_AVDD10_LEVEL_MASK;
2700 value &= ~SOR_PLL3_AVDD14_LEVEL_MASK;
2701 value |= SOR_PLL3_BG_TEMP_COEF(settings->bg_temp_coef);
2702 value |= SOR_PLL3_BG_VREF_LEVEL(settings->bg_vref_level);
2703 value |= SOR_PLL3_AVDD10_LEVEL(settings->avdd10_level);
2704 value |= SOR_PLL3_AVDD14_LEVEL(settings->avdd14_level);
2705 tegra_sor_writel(sor, value, sor->soc->regs->pll3);
2706
2707 value = settings->drive_current[3] << 24 |
2708 settings->drive_current[2] << 16 |
2709 settings->drive_current[1] << 8 |
2710 settings->drive_current[0] << 0;
2711 tegra_sor_writel(sor, value, SOR_LANE_DRIVE_CURRENT0);
2712
2713 value = settings->preemphasis[3] << 24 |
2714 settings->preemphasis[2] << 16 |
2715 settings->preemphasis[1] << 8 |
2716 settings->preemphasis[0] << 0;
2717 tegra_sor_writel(sor, value, SOR_LANE_PREEMPHASIS0);
2718
2719 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2720 value &= ~SOR_DP_PADCTL_TX_PU_MASK;
2721 value |= SOR_DP_PADCTL_TX_PU_ENABLE;
2722 value |= SOR_DP_PADCTL_TX_PU(settings->tx_pu_value);
2723 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2724
2725 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl2);
2726 value &= ~SOR_DP_PADCTL_SPAREPLL_MASK;
2727 value |= SOR_DP_PADCTL_SPAREPLL(settings->sparepll);
2728 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl2);
2729
2730 /* power down pad calibration */
2731 value = tegra_sor_readl(sor, sor->soc->regs->dp_padctl0);
2732 value |= SOR_DP_PADCTL_PAD_CAL_PD;
2733 tegra_sor_writel(sor, value, sor->soc->regs->dp_padctl0);
2734
2735 if (!dc->soc->has_nvdisplay) {
2736 /* miscellaneous display controller settings */
2737 value = VSYNC_H_POSITION(1);
2738 tegra_dc_writel(dc, value, DC_DISP_DISP_TIMING_OPTIONS);
2739 }
2740
2741 value = tegra_dc_readl(dc, DC_DISP_DISP_COLOR_CONTROL);
2742 value &= ~DITHER_CONTROL_MASK;
2743 value &= ~BASE_COLOR_SIZE_MASK;
2744
2745 if (dc->soc->has_nvdisplay) {
2746 sor->cmu_output_lut =
2747 dma_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
2748 &sor->cmu_output_phys, GFP_KERNEL);
2749
2750 for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
2751 r = default_srgb_lut[i];
2752 sor->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
2753 }
2754
2755 tegra_dc_writel(dc, (u32)(sor->cmu_output_phys & 0xffffffff),
2756 DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
> 2757 tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
2758 DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
2759
2760 tegra_dc_writel(dc, OUTPUT_LUT_MODE_INTERPOLATE | OUTPUT_LUT_SIZE_SIZE_1025,
2761 DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT);
2762
2763 value |= CMU_ENABLE_ENABLE;
2764 }
2765
2766 switch (state->bpc) {
2767 case 6:
2768 value |= BASE_COLOR_SIZE_666;
2769 break;
2770
2771 case 8:
2772 value |= BASE_COLOR_SIZE_888;
2773 break;
2774
2775 case 10:
2776 value |= BASE_COLOR_SIZE_101010;
2777 break;
2778
2779 case 12:
2780 value |= BASE_COLOR_SIZE_121212;
2781 break;
2782
2783 default:
2784 WARN(1, "%u bits-per-color not supported\n", state->bpc);
2785 value |= BASE_COLOR_SIZE_888;
2786 break;
2787 }
2788
2789 tegra_dc_writel(dc, value, DC_DISP_DISP_COLOR_CONTROL);
2790
2791 /* XXX set display head owner */
2792 value = tegra_sor_readl(sor, SOR_STATE1);
2793 value &= ~SOR_STATE_ASY_OWNER_MASK;
2794 value |= SOR_STATE_ASY_OWNER(1 + dc->pipe);
2795 tegra_sor_writel(sor, value, SOR_STATE1);
2796
2797 err = tegra_sor_power_up(sor, 250);
2798 if (err < 0)
2799 dev_err(sor->dev, "failed to power up SOR: %d\n", err);
2800
2801 /* configure dynamic range of output */
2802 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
2803 value &= ~SOR_HEAD_STATE_RANGECOMPRESS_MASK;
2804 value &= ~SOR_HEAD_STATE_DYNRANGE_MASK;
2805 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
2806
2807 /* configure colorspace */
2808 value = tegra_sor_readl(sor, sor->soc->regs->head_state0 + dc->pipe);
2809 value &= ~SOR_HEAD_STATE_COLORSPACE_MASK;
2810 value |= SOR_HEAD_STATE_COLORSPACE_RGB;
2811 tegra_sor_writel(sor, value, sor->soc->regs->head_state0 + dc->pipe);
2812
2813 tegra_sor_mode_set(sor, mode, state);
2814
2815 tegra_sor_update(sor);
2816
2817 /* program preamble timing in SOR (XXX) */
2818 value = tegra_sor_readl(sor, SOR_DP_SPARE0);
2819 value &= ~SOR_DP_SPARE_DISP_VIDEO_PREAMBLE;
2820 tegra_sor_writel(sor, value, SOR_DP_SPARE0);
2821
2822 err = tegra_sor_attach(sor);
2823 if (err < 0)
2824 dev_err(sor->dev, "failed to attach SOR: %d\n", err);
2825
2826 /* enable display to SOR clock and generate HDMI preamble */
2827 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
2828
2829 if (!sor->soc->has_nvdisplay)
2830 value |= SOR1_TIMING_CYA;
2831
2832 value |= SOR_ENABLE(sor->index);
2833
2834 tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
2835
2836 if (dc->soc->has_nvdisplay) {
2837 value = tegra_dc_readl(dc, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2838 value &= ~PROTOCOL_MASK;
2839 value |= PROTOCOL_SINGLE_TMDS_A;
2840 tegra_dc_writel(dc, value, DC_DISP_CORE_SOR_SET_CONTROL(sor->index));
2841 }
2842
2843 tegra_dc_commit(dc);
2844
2845 err = tegra_sor_wakeup(sor);
2846 if (err < 0)
2847 dev_err(sor->dev, "failed to wakeup SOR: %d\n", err);
2848
2849 tegra_sor_hdmi_scdc_start(sor);
2850 tegra_sor_audio_prepare(sor);
2851 }
2852
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-01 23:15 [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194 Aaron Kling via B4 Relay
2025-11-02 17:03 ` kernel test robot
2025-11-02 17:44 ` kernel test robot
@ 2025-11-03 11:54 ` Thierry Reding
2025-11-03 18:39 ` Aaron Kling
2 siblings, 1 reply; 8+ messages in thread
From: Thierry Reding @ 2025-11-03 11:54 UTC (permalink / raw)
To: webgeek1234
Cc: Mikko Perttunen, David Airlie, Simona Vetter, Jonathan Hunter,
dri-devel, linux-tegra, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 6118 bytes --]
On Sat, Nov 01, 2025 at 06:15:17PM -0500, Aaron Kling via B4 Relay wrote:
> From: Aaron Kling <webgeek1234@gmail.com>
>
> Without the cmu, nvdisplay will display colors that are notably darker
> than intended. The vendor bootloader and the downstream display driver
> enable the cmu and sets a sRGB table. Loading that table here results in
> the intended colors.
>
> Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> ---
> drivers/gpu/drm/tegra/dc.h | 13 +++
> drivers/gpu/drm/tegra/sor.c | 206 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 219 insertions(+)
What does "darker than intended" mean? Who defines the intention? How do
we know what the intention is? What this patch ultimately seems to be
doing is define sRGB to be the default colorspace. Is that always the
right default choice? What if people want to specify a different
colorspace?
Looking at the enum dp_colorimetry it seems like sRGB is the default for
DP at least. But then it says the default is sRGB or ITU-R BT.601, but
if I compare that to the Wikipedia article for sRGB that says sRGB is
closer to ITU-R BT.709 than BT.601. Can we narrow in what exactly the
LUT in this patch corresponds to?
> diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> index 0559fa6b1bf70416e51d5067cc04a6ae6572de23..286eddd89a28f7ea9e64c00f03af76f6c68ae9d8 100644
> --- a/drivers/gpu/drm/tegra/dc.h
> +++ b/drivers/gpu/drm/tegra/dc.h
> @@ -447,11 +447,24 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
> #define BASE_COLOR_SIZE_888 ( 8 << 0)
> #define BASE_COLOR_SIZE_101010 ( 10 << 0)
> #define BASE_COLOR_SIZE_121212 ( 12 << 0)
> +#define CMU_ENABLE_MASK (1 << 20)
> +#define CMU_ENABLE_DISABLE (0 << 20)
> +#define CMU_ENABLE_ENABLE (1 << 20)
_MASK and _DISABLE are unused (and also quite useless in this case).
>
> #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
> #define SC1_H_QUALIFIER_NONE (1 << 16)
> #define SC0_H_QUALIFIER_NONE (1 << 0)
>
> +/* Nvdisplay */
> +#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT 0x431
> +#define OUTPUT_LUT_MODE_MASK (3 << 5)
> +#define OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
> +#define OUTPUT_LUT_SIZE_MASK (3 << 1)
> +#define OUTPUT_LUT_SIZE_SIZE_1025 (2 << 1)
> +
> +#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE 0x432
> +#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI 0x433
> +
There's a section in this header titled "Tegra186 and later", where
these new definitions should go. Anything in this section is part of the
old registers (or the emulated ones for backwards compatibility).
> #define DC_DISP_DATA_ENABLE_OPTIONS 0x432
> #define DE_SELECT_ACTIVE_BLANK (0 << 0)
> #define DE_SELECT_ACTIVE (1 << 0)
> diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> index 21f3dfdcc5c9576580b9aa9990dd1bedcdeb4482..a381cb35113c0f3191d7204302f4024f33141622 100644
> --- a/drivers/gpu/drm/tegra/sor.c
> +++ b/drivers/gpu/drm/tegra/sor.c
> @@ -443,6 +443,9 @@ struct tegra_sor {
> bool scdc_enabled;
>
> struct tegra_hda_format format;
> +
> + u64 *cmu_output_lut;
> + dma_addr_t cmu_output_phys;
> };
>
> struct tegra_sor_state {
> @@ -483,6 +486,180 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output)
> return container_of(output, struct tegra_sor, output);
> }
>
> +static u16 default_srgb_lut[] = {
> + 0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4,
[...]
> + 0x9FE2, 0x9FE9, 0x9FF0, 0x9FF7, 0x9FFF,
> +};
I don't take it there's a way to generate this table? And these are not
standard values that could be shared among different drivers?
You could probably make this a bit more compact by indenting the data
with a single tab and squeeze in 2 or 3 more values per line.
> static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset)
> {
> u32 value = readl(sor->regs + (offset << 2));
> @@ -2241,6 +2418,13 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
> dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
>
> host1x_client_suspend(&sor->client);
> +
> + if (sor->soc->has_nvdisplay) {
> + dma_free_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
> + sor->cmu_output_lut, sor->cmu_output_phys);
> + sor->cmu_output_lut = NULL;
> + sor->cmu_output_phys = 0;
> + }
> }
>
> static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
> @@ -2255,6 +2439,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
> unsigned long rate, pclk;
> unsigned int div, i;
> u32 value;
> + u64 r;
This can be moved into the branch to narrow the scope.
> int err;
>
> state = to_sor_state(output->connector.state);
> @@ -2557,6 +2742,27 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
> value &= ~DITHER_CONTROL_MASK;
> value &= ~BASE_COLOR_SIZE_MASK;
>
> + if (dc->soc->has_nvdisplay) {
> + sor->cmu_output_lut =
> + dma_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
> + &sor->cmu_output_phys, GFP_KERNEL);
You need to check for failure, otherwise you might NULL dereference the
pointer below. But then it's probably even better to allocate this at
probe time so that we can guarantee that the LUT can always be set.
> +
> + for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
> + r = default_srgb_lut[i];
> + sor->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
> + }
Given that this was taken from the downstream driver, this is probably
correct, but I'm not sure I understand why the same value is written to
the LUT thrice. Do you happen to know?
> + tegra_dc_writel(dc, (u32)(sor->cmu_output_phys & 0xffffffff),
> + DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
> + tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
> + DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
You'll want to use the lower_32_bits() and upper_32_bits() functions
like we do for other address values (see hub.c, for example).
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-03 11:54 ` Thierry Reding
@ 2025-11-03 18:39 ` Aaron Kling
2025-11-04 9:14 ` Thierry Reding
0 siblings, 1 reply; 8+ messages in thread
From: Aaron Kling @ 2025-11-03 18:39 UTC (permalink / raw)
To: Thierry Reding
Cc: Mikko Perttunen, David Airlie, Simona Vetter, Jonathan Hunter,
dri-devel, linux-tegra, linux-kernel
On Mon, Nov 3, 2025 at 5:54 AM Thierry Reding <thierry.reding@gmail.com> wrote:
>
> On Sat, Nov 01, 2025 at 06:15:17PM -0500, Aaron Kling via B4 Relay wrote:
> > From: Aaron Kling <webgeek1234@gmail.com>
> >
> > Without the cmu, nvdisplay will display colors that are notably darker
> > than intended. The vendor bootloader and the downstream display driver
> > enable the cmu and sets a sRGB table. Loading that table here results in
> > the intended colors.
> >
> > Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> > ---
> > drivers/gpu/drm/tegra/dc.h | 13 +++
> > drivers/gpu/drm/tegra/sor.c | 206 ++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 219 insertions(+)
>
> What does "darker than intended" mean? Who defines the intention? How do
> we know what the intention is? What this patch ultimately seems to be
> doing is define sRGB to be the default colorspace. Is that always the
> right default choice? What if people want to specify a different
> colorspace?
I reported this issue almost a month ago. See kernel lore [0] and
freedesktop issue [1]. The pictures in the latter show what nvdisplay
looks like right now. It's nigh unusably dark. When booted into
Android with a tv launcher that has a black background, as is default
for LineageOS, it is really hard to read anything. Is it correct as a
default? Well, cboot hardcodes this, so... presumably? It would be
more ideal to expose this and csc to userspace, but I'm not sure if
drm has a standardized interface for that or if tegra would have to
make something vendor specific. I think that would be a separate
change concept compared to setting this default, though.
> Looking at the enum dp_colorimetry it seems like sRGB is the default for
> DP at least. But then it says the default is sRGB or ITU-R BT.601, but
> if I compare that to the Wikipedia article for sRGB that says sRGB is
> closer to ITU-R BT.709 than BT.601. Can we narrow in what exactly the
> LUT in this patch corresponds to?
I really don't know. While trying to fix the broken colors, I came
across the same table in cboot [2] and the downstream tegradc driver.
Cboot was released as a tarball with no commit history. And the
tegradc commit history did not have any further clarification beyond
'sRGB'.
> > diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
> > index 0559fa6b1bf70416e51d5067cc04a6ae6572de23..286eddd89a28f7ea9e64c00f03af76f6c68ae9d8 100644
> > --- a/drivers/gpu/drm/tegra/dc.h
> > +++ b/drivers/gpu/drm/tegra/dc.h
> > @@ -447,11 +447,24 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
> > #define BASE_COLOR_SIZE_888 ( 8 << 0)
> > #define BASE_COLOR_SIZE_101010 ( 10 << 0)
> > #define BASE_COLOR_SIZE_121212 ( 12 << 0)
> > +#define CMU_ENABLE_MASK (1 << 20)
> > +#define CMU_ENABLE_DISABLE (0 << 20)
> > +#define CMU_ENABLE_ENABLE (1 << 20)
>
> _MASK and _DISABLE are unused (and also quite useless in this case).
Fair. I was trying to match the style of the rest of the header, but I
can drop the unused defines.
>
> >
> > #define DC_DISP_SHIFT_CLOCK_OPTIONS 0x431
> > #define SC1_H_QUALIFIER_NONE (1 << 16)
> > #define SC0_H_QUALIFIER_NONE (1 << 0)
> >
> > +/* Nvdisplay */
> > +#define DC_DISP_CORE_HEAD_SET_CONTROL_OUTPUT_LUT 0x431
> > +#define OUTPUT_LUT_MODE_MASK (3 << 5)
> > +#define OUTPUT_LUT_MODE_INTERPOLATE (1 << 5)
> > +#define OUTPUT_LUT_SIZE_MASK (3 << 1)
> > +#define OUTPUT_LUT_SIZE_SIZE_1025 (2 << 1)
> > +
> > +#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE 0x432
> > +#define DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI 0x433
> > +
>
> There's a section in this header titled "Tegra186 and later", where
> these new definitions should go. Anything in this section is part of the
> old registers (or the emulated ones for backwards compatibility).
I figured there had to be a section for that somewhere, but my
searches failed me. I see it now and will move.
> > #define DC_DISP_DATA_ENABLE_OPTIONS 0x432
> > #define DE_SELECT_ACTIVE_BLANK (0 << 0)
> > #define DE_SELECT_ACTIVE (1 << 0)
> > diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
> > index 21f3dfdcc5c9576580b9aa9990dd1bedcdeb4482..a381cb35113c0f3191d7204302f4024f33141622 100644
> > --- a/drivers/gpu/drm/tegra/sor.c
> > +++ b/drivers/gpu/drm/tegra/sor.c
> > @@ -443,6 +443,9 @@ struct tegra_sor {
> > bool scdc_enabled;
> >
> > struct tegra_hda_format format;
> > +
> > + u64 *cmu_output_lut;
> > + dma_addr_t cmu_output_phys;
> > };
> >
> > struct tegra_sor_state {
> > @@ -483,6 +486,180 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output)
> > return container_of(output, struct tegra_sor, output);
> > }
> >
> > +static u16 default_srgb_lut[] = {
> > + 0x6000, 0x60CE, 0x619D, 0x626C, 0x632D, 0x63D4,
> [...]
> > + 0x9FE2, 0x9FE9, 0x9FF0, 0x9FF7, 0x9FFF,
> > +};
>
> I don't take it there's a way to generate this table? And these are not
> standard values that could be shared among different drivers?
I don't know of a way to generate it. As mentioned above, this was
copied from downstream.
As for sharing, I don't know. If I read the tx2 trm correctly, the
display pipeline goes through a input LUT, which is not currently
enabled by tegra-drm, then into csc, which expects some 'linear
colorspace'. Then that outputs into the output LUT, which is labelled
as the cmu, which is expected to translate from that linear colorspace
into the colorspace expected by the display. Given that this LUT
generates expected colors on my displays, I assume that the pixels in
the pipeline are in that 'linear colorspace'. I'm not sure if that's a
standardized thing or something nvdisplay specific. If it is the
latter, then the table wouldn't be useful anywhere else.
> You could probably make this a bit more compact by indenting the data
> with a single tab and squeeze in 2 or 3 more values per line.
Ack.
> > static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned int offset)
> > {
> > u32 value = readl(sor->regs + (offset << 2));
> > @@ -2241,6 +2418,13 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder)
> > dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
> >
> > host1x_client_suspend(&sor->client);
> > +
> > + if (sor->soc->has_nvdisplay) {
> > + dma_free_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
> > + sor->cmu_output_lut, sor->cmu_output_phys);
> > + sor->cmu_output_lut = NULL;
> > + sor->cmu_output_phys = 0;
> > + }
> > }
> >
> > static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
> > @@ -2255,6 +2439,7 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
> > unsigned long rate, pclk;
> > unsigned int div, i;
> > u32 value;
> > + u64 r;
>
> This can be moved into the branch to narrow the scope.
Ack.
>
> > int err;
> >
> > state = to_sor_state(output->connector.state);
> > @@ -2557,6 +2742,27 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
> > value &= ~DITHER_CONTROL_MASK;
> > value &= ~BASE_COLOR_SIZE_MASK;
> >
> > + if (dc->soc->has_nvdisplay) {
> > + sor->cmu_output_lut =
> > + dma_alloc_coherent(dc->dev, ARRAY_SIZE(default_srgb_lut) * sizeof(u64),
> > + &sor->cmu_output_phys, GFP_KERNEL);
>
> You need to check for failure, otherwise you might NULL dereference the
> pointer below. But then it's probably even better to allocate this at
> probe time so that we can guarantee that the LUT can always be set.
Moving alloc to probe and free to remove makes sense. Less thrashing
that way too. Will do.
> > +
> > + for (i = 0; i < ARRAY_SIZE(default_srgb_lut); i++) {
> > + r = default_srgb_lut[i];
> > + sor->cmu_output_lut[i] = (r << 32) | (r << 16) | r;
> > + }
>
> Given that this was taken from the downstream driver, this is probably
> correct, but I'm not sure I understand why the same value is written to
> the LUT thrice. Do you happen to know?
I do not, no. I wondered at that too.
>
> > + tegra_dc_writel(dc, (u32)(sor->cmu_output_phys & 0xffffffff),
> > + DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE);
> > + tegra_dc_writel(dc, (u32)(sor->cmu_output_phys >> 32),
> > + DC_DISP_COREPVT_HEAD_SET_OUTPUT_LUT_BASE_HI);
>
> You'll want to use the lower_32_bits() and upper_32_bits() functions
> like we do for other address values (see hub.c, for example).
Ack.
I will stage the code review changes, but will hold off on sending a
new revision. Pending any additional changes coming from the
discussion of the concept in general.
Aaron
[0] https://lore.kernel.org/all/CALHNRZ_vMy1CTosZ=ymOhAyMNRh+oBOU9NJ8Gvr8EkqQ5XjFDw@mail.gmail.com/
[1] https://gitlab.freedesktop.org/drm/tegra/-/issues/8
[2] https://github.com/LineageOS/android_bootable_cboot_common/blob/034b04d3ac7f2f80d72e3b894d97da4f6e2cd591/drivers/display/nvdisp/tegrabl_nvdisp_cmu.c#L24
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-03 18:39 ` Aaron Kling
@ 2025-11-04 9:14 ` Thierry Reding
2025-11-04 18:12 ` Aaron Kling
0 siblings, 1 reply; 8+ messages in thread
From: Thierry Reding @ 2025-11-04 9:14 UTC (permalink / raw)
To: Aaron Kling
Cc: Mikko Perttunen, David Airlie, Simona Vetter, Jonathan Hunter,
dri-devel, linux-tegra, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2353 bytes --]
On Mon, Nov 03, 2025 at 12:39:57PM -0600, Aaron Kling wrote:
> On Mon, Nov 3, 2025 at 5:54 AM Thierry Reding <thierry.reding@gmail.com> wrote:
> >
> > On Sat, Nov 01, 2025 at 06:15:17PM -0500, Aaron Kling via B4 Relay wrote:
> > > From: Aaron Kling <webgeek1234@gmail.com>
> > >
> > > Without the cmu, nvdisplay will display colors that are notably darker
> > > than intended. The vendor bootloader and the downstream display driver
> > > enable the cmu and sets a sRGB table. Loading that table here results in
> > > the intended colors.
> > >
> > > Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> > > ---
> > > drivers/gpu/drm/tegra/dc.h | 13 +++
> > > drivers/gpu/drm/tegra/sor.c | 206 ++++++++++++++++++++++++++++++++++++++++++++
> > > 2 files changed, 219 insertions(+)
> >
> > What does "darker than intended" mean? Who defines the intention? How do
> > we know what the intention is? What this patch ultimately seems to be
> > doing is define sRGB to be the default colorspace. Is that always the
> > right default choice? What if people want to specify a different
> > colorspace?
>
> I reported this issue almost a month ago. See kernel lore [0] and
> freedesktop issue [1]. The pictures in the latter show what nvdisplay
> looks like right now. It's nigh unusably dark. When booted into
> Android with a tv launcher that has a black background, as is default
> for LineageOS, it is really hard to read anything. Is it correct as a
> default? Well, cboot hardcodes this, so... presumably? It would be
> more ideal to expose this and csc to userspace, but I'm not sure if
> drm has a standardized interface for that or if tegra would have to
> make something vendor specific. I think that would be a separate
> change concept compared to setting this default, though.
The reason I'm asking is because I don't recall ever seeing "broken"
colors like you do. So I suspect that this may also be related to what
display is connected, or the mode that we're setting. It could perhaps
also be related to what infoframes we're sending and how these are
supported/interpreted by the attached display.
All of that is to say that maybe this looks broken on the particular
setup that you have but may works fine on other setups. Changing the
default may fix your setup and break others.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-04 9:14 ` Thierry Reding
@ 2025-11-04 18:12 ` Aaron Kling
2025-11-05 21:28 ` Jasper Korten
0 siblings, 1 reply; 8+ messages in thread
From: Aaron Kling @ 2025-11-04 18:12 UTC (permalink / raw)
To: Thierry Reding
Cc: Mikko Perttunen, David Airlie, Simona Vetter, Jonathan Hunter,
dri-devel, linux-tegra, linux-kernel
On Tue, Nov 4, 2025 at 3:14 AM Thierry Reding <thierry.reding@gmail.com> wrote:
>
> On Mon, Nov 03, 2025 at 12:39:57PM -0600, Aaron Kling wrote:
> > On Mon, Nov 3, 2025 at 5:54 AM Thierry Reding <thierry.reding@gmail.com> wrote:
> > >
> > > On Sat, Nov 01, 2025 at 06:15:17PM -0500, Aaron Kling via B4 Relay wrote:
> > > > From: Aaron Kling <webgeek1234@gmail.com>
> > > >
> > > > Without the cmu, nvdisplay will display colors that are notably darker
> > > > than intended. The vendor bootloader and the downstream display driver
> > > > enable the cmu and sets a sRGB table. Loading that table here results in
> > > > the intended colors.
> > > >
> > > > Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
> > > > ---
> > > > drivers/gpu/drm/tegra/dc.h | 13 +++
> > > > drivers/gpu/drm/tegra/sor.c | 206 ++++++++++++++++++++++++++++++++++++++++++++
> > > > 2 files changed, 219 insertions(+)
> > >
> > > What does "darker than intended" mean? Who defines the intention? How do
> > > we know what the intention is? What this patch ultimately seems to be
> > > doing is define sRGB to be the default colorspace. Is that always the
> > > right default choice? What if people want to specify a different
> > > colorspace?
> >
> > I reported this issue almost a month ago. See kernel lore [0] and
> > freedesktop issue [1]. The pictures in the latter show what nvdisplay
> > looks like right now. It's nigh unusably dark. When booted into
> > Android with a tv launcher that has a black background, as is default
> > for LineageOS, it is really hard to read anything. Is it correct as a
> > default? Well, cboot hardcodes this, so... presumably? It would be
> > more ideal to expose this and csc to userspace, but I'm not sure if
> > drm has a standardized interface for that or if tegra would have to
> > make something vendor specific. I think that would be a separate
> > change concept compared to setting this default, though.
>
> The reason I'm asking is because I don't recall ever seeing "broken"
> colors like you do. So I suspect that this may also be related to what
> display is connected, or the mode that we're setting. It could perhaps
> also be related to what infoframes we're sending and how these are
> supported/interpreted by the attached display.
>
> All of that is to say that maybe this looks broken on the particular
> setup that you have but may works fine on other setups. Changing the
> default may fix your setup and break others.
Do you have a device set up so you can check? Or does the regression
test bench have a display that can be forwarded?
My current setup is a rack of units plugged via hdmi to a kvm which is
then plugged to a pikvm. I also observed this issue before I had this
setup, plugged directly to a 1080p monitor. I have not checked
displayport. I can cycle through a couple other displays without this
patch to see if I get any other result. I am fairly certain I have
consistently seen this issue since I started trying to work with
tegra-drm on kernel 6.1 or maybe even 5.15. I've never seen it work to
allow for a bisect.
I am in contact with one other person with a tx2 devkit, who
replicated the issue when I asked. Who plans to reply to this thread
with setup info later.
Aaron
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194
2025-11-04 18:12 ` Aaron Kling
@ 2025-11-05 21:28 ` Jasper Korten
0 siblings, 0 replies; 8+ messages in thread
From: Jasper Korten @ 2025-11-05 21:28 UTC (permalink / raw)
To: Aaron Kling, Thierry Reding
Cc: Mikko Perttunen, David Airlie, Simona Vetter, Jonathan Hunter,
dri-devel, linux-tegra, linux-kernel
Hi all,
On 11/4/25 19:12, Aaron Kling wrote:
> On Tue, Nov 4, 2025 at 3:14 AM Thierry Reding <thierry.reding@gmail.com> wrote:
>> On Mon, Nov 03, 2025 at 12:39:57PM -0600, Aaron Kling wrote:
>>> On Mon, Nov 3, 2025 at 5:54 AM Thierry Reding <thierry.reding@gmail.com> wrote:
>>>> On Sat, Nov 01, 2025 at 06:15:17PM -0500, Aaron Kling via B4 Relay wrote:
>>>>> From: Aaron Kling <webgeek1234@gmail.com>
>>>>>
>>>>> Without the cmu, nvdisplay will display colors that are notably darker
>>>>> than intended. The vendor bootloader and the downstream display driver
>>>>> enable the cmu and sets a sRGB table. Loading that table here results in
>>>>> the intended colors.
>>>>>
>>>>> Signed-off-by: Aaron Kling <webgeek1234@gmail.com>
>>>>> ---
>>>>> drivers/gpu/drm/tegra/dc.h | 13 +++
>>>>> drivers/gpu/drm/tegra/sor.c | 206 ++++++++++++++++++++++++++++++++++++++++++++
>>>>> 2 files changed, 219 insertions(+)
>>>> What does "darker than intended" mean? Who defines the intention? How do
>>>> we know what the intention is? What this patch ultimately seems to be
>>>> doing is define sRGB to be the default colorspace. Is that always the
>>>> right default choice? What if people want to specify a different
>>>> colorspace?
>>> I reported this issue almost a month ago. See kernel lore [0] and
>>> freedesktop issue [1]. The pictures in the latter show what nvdisplay
>>> looks like right now. It's nigh unusably dark. When booted into
>>> Android with a tv launcher that has a black background, as is default
>>> for LineageOS, it is really hard to read anything. Is it correct as a
>>> default? Well, cboot hardcodes this, so... presumably? It would be
>>> more ideal to expose this and csc to userspace, but I'm not sure if
>>> drm has a standardized interface for that or if tegra would have to
>>> make something vendor specific. I think that would be a separate
>>> change concept compared to setting this default, though.
>> The reason I'm asking is because I don't recall ever seeing "broken"
>> colors like you do. So I suspect that this may also be related to what
>> display is connected, or the mode that we're setting.
I have tried it on both a MacroSilicon HDMI capture card and an Arzopa
Z1FC 1080p portable monitor and run into the same darker colors. Both
have in common that they use HDMI which seems to line up with what Aaron
is reporting. I do not have an eDP display to test or another carrier
board with a different display out to test.
>> It could perhaps
>> also be related to what infoframes we're sending and how these are
>> supported/interpreted by the attached display.
>>
>> All of that is to say that maybe this looks broken on the particular
>> setup that you have but may works fine on other setups. Changing the
>> default may fix your setup and break others.
> Do you have a device set up so you can check? Or does the regression
> test bench have a display that can be forwarded?
>
> My current setup is a rack of units plugged via hdmi to a kvm which is
> then plugged to a pikvm. I also observed this issue before I had this
> setup, plugged directly to a 1080p monitor. I have not checked
> displayport. I can cycle through a couple other displays without this
> patch to see if I get any other result. I am fairly certain I have
> consistently seen this issue since I started trying to work with
> tegra-drm on kernel 6.1 or maybe even 5.15. I've never seen it work to
> allow for a bisect.
>
> I am in contact with one other person with a tx2 devkit, who
> replicated the issue when I asked. Who plans to reply to this thread
> with setup info later.
For reference, I am said person. I have a Jetson TX2 Devkit that uses
the P2771 Device Tree. I'm running a Fedora distrokernel with no
additional patches applied by myself. I have personally noticed the
issue to at least be present on 6.14.5 and 6.17.4.
I'm currently not at home to take screenshots with and without the
submitted patch, but will be able to do it tomorrownight or friday.
Kindest regards,
Jasper
>
> Aaron
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-11-05 21:28 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-01 23:15 [PATCH] drm/tegra: Enable cmu for Tegra186 and Tegra194 Aaron Kling via B4 Relay
2025-11-02 17:03 ` kernel test robot
2025-11-02 17:44 ` kernel test robot
2025-11-03 11:54 ` Thierry Reding
2025-11-03 18:39 ` Aaron Kling
2025-11-04 9:14 ` Thierry Reding
2025-11-04 18:12 ` Aaron Kling
2025-11-05 21:28 ` Jasper Korten
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).