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/stm: ltdc: support new hardware version for STM32MP25 SoC

STM32MP25 SoC features a new version of the LTDC IP. Add its compatible
to the list of device to probe and implement its quirks.

This hardware supports a pad frequency of 150MHz and a peripheral bus
clock.

Signed-off-by: Yannick Fertre <yannick.fertre@foss.st.com>
Acked-by: Yannick Fertre <yannick.fertre@foss.st.com>
Acked-by: Philippe Cornu <philippe.cornu@foss.st.com>
Link: https://lore.kernel.org/r/20250822-drm-misc-next-v5-7-9c825e28f733@foss.st.com
Signed-off-by: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>

authored by

Yannick Fertre and committed by
Raphael Gallais-Pou
d8066764 1b9482f8

+51 -4
+11 -1
drivers/gpu/drm/stm/drv.c
··· 236 236 drm_atomic_helper_shutdown(platform_get_drvdata(pdev)); 237 237 } 238 238 239 + static struct ltdc_plat_data stm_drm_plat_data = { 240 + .pad_max_freq_hz = 90000000, 241 + }; 242 + 243 + static struct ltdc_plat_data stm_drm_plat_data_mp25 = { 244 + .pad_max_freq_hz = 150000000, 245 + }; 246 + 239 247 static const struct of_device_id drv_dt_ids[] = { 240 - { .compatible = "st,stm32-ltdc"}, 248 + { .compatible = "st,stm32-ltdc", .data = &stm_drm_plat_data, }, 249 + { .compatible = "st,stm32mp251-ltdc", .data = &stm_drm_plat_data_mp25, }, 250 + { .compatible = "st,stm32mp255-ltdc", .data = &stm_drm_plat_data_mp25, }, 241 251 { /* end node */ }, 242 252 }; 243 253 MODULE_DEVICE_TABLE(of, drv_dt_ids);
+35 -3
drivers/gpu/drm/stm/ltdc.c
··· 14 14 #include <linux/interrupt.h> 15 15 #include <linux/media-bus-format.h> 16 16 #include <linux/module.h> 17 + #include <linux/of.h> 17 18 #include <linux/of_graph.h> 18 19 #include <linux/pinctrl/consumer.h> 19 20 #include <linux/platform_device.h> ··· 52 51 #define HWVER_10300 0x010300 53 52 #define HWVER_20101 0x020101 54 53 #define HWVER_40100 0x040100 54 + #define HWVER_40101 0x040101 55 55 56 56 /* 57 57 * The address of some registers depends on the HW version: such registers have ··· 1782 1780 { 1783 1781 struct ltdc_device *ldev = ddev->dev_private; 1784 1782 u32 bus_width_log2, lcr, gc2r; 1783 + const struct ltdc_plat_data *pdata = of_device_get_match_data(ddev->dev); 1785 1784 1786 1785 /* 1787 1786 * at least 1 layer must be managed & the number of layers ··· 1797 1794 bus_width_log2 = (gc2r & GC2R_BW) >> 4; 1798 1795 ldev->caps.bus_width = 8 << bus_width_log2; 1799 1796 regmap_read(ldev->regmap, LTDC_IDR, &ldev->caps.hw_version); 1797 + 1798 + ldev->caps.pad_max_freq_hz = pdata->pad_max_freq_hz; 1800 1799 1801 1800 switch (ldev->caps.hw_version) { 1802 1801 case HWVER_10200: ··· 1817 1812 * does not work on 2nd layer. 1818 1813 */ 1819 1814 ldev->caps.non_alpha_only_l1 = true; 1820 - ldev->caps.pad_max_freq_hz = 90000000; 1821 1815 if (ldev->caps.hw_version == HWVER_10200) 1822 1816 ldev->caps.pad_max_freq_hz = 65000000; 1823 1817 ldev->caps.nb_irq = 2; ··· 1847 1843 ldev->caps.fifo_threshold = false; 1848 1844 break; 1849 1845 case HWVER_40100: 1846 + case HWVER_40101: 1850 1847 ldev->caps.layer_ofs = LAY_OFS_1; 1851 1848 ldev->caps.layer_regs = ltdc_layer_regs_a2; 1852 1849 ldev->caps.pix_fmt_hw = ltdc_pix_fmt_a2; ··· 1855 1850 ldev->caps.pix_fmt_nb = ARRAY_SIZE(ltdc_drm_fmt_a2); 1856 1851 ldev->caps.pix_fmt_flex = true; 1857 1852 ldev->caps.non_alpha_only_l1 = false; 1858 - ldev->caps.pad_max_freq_hz = 90000000; 1859 1853 ldev->caps.nb_irq = 2; 1860 1854 ldev->caps.ycbcr_input = true; 1861 1855 ldev->caps.ycbcr_output = true; ··· 1877 1873 1878 1874 drm_dbg_driver(ddev, "\n"); 1879 1875 clk_disable_unprepare(ldev->pixel_clk); 1876 + if (ldev->bus_clk) 1877 + clk_disable_unprepare(ldev->bus_clk); 1880 1878 } 1881 1879 1882 1880 int ltdc_resume(struct drm_device *ddev) ··· 1894 1888 return ret; 1895 1889 } 1896 1890 1897 - return 0; 1891 + if (ldev->bus_clk) { 1892 + ret = clk_prepare_enable(ldev->bus_clk); 1893 + if (ret) 1894 + drm_err(ddev, "failed to enable bus clock (%d)\n", ret); 1895 + } 1896 + 1897 + return ret; 1898 1898 } 1899 1899 1900 1900 int ltdc_load(struct drm_device *ddev) ··· 1933 1921 if (clk_prepare_enable(ldev->pixel_clk)) { 1934 1922 drm_err(ddev, "Unable to prepare pixel clock\n"); 1935 1923 return -ENODEV; 1924 + } 1925 + 1926 + if (of_device_is_compatible(np, "st,stm32mp251-ltdc") || 1927 + of_device_is_compatible(np, "st,stm32mp255-ltdc")) { 1928 + ldev->bus_clk = devm_clk_get(dev, "bus"); 1929 + if (IS_ERR(ldev->bus_clk)) 1930 + return dev_err_probe(dev, PTR_ERR(ldev->bus_clk), 1931 + "Unable to get bus clock\n"); 1932 + 1933 + ret = clk_prepare_enable(ldev->bus_clk); 1934 + if (ret) { 1935 + drm_err(ddev, "Unable to prepare bus clock\n"); 1936 + return ret; 1937 + } 1936 1938 } 1937 1939 1938 1940 /* Get endpoints if any */ ··· 2061 2035 2062 2036 clk_disable_unprepare(ldev->pixel_clk); 2063 2037 2038 + if (ldev->bus_clk) 2039 + clk_disable_unprepare(ldev->bus_clk); 2040 + 2064 2041 pinctrl_pm_select_sleep_state(ddev->dev); 2065 2042 2066 2043 pm_runtime_enable(ddev->dev); ··· 2071 2042 return 0; 2072 2043 err: 2073 2044 clk_disable_unprepare(ldev->pixel_clk); 2045 + 2046 + if (ldev->bus_clk) 2047 + clk_disable_unprepare(ldev->bus_clk); 2074 2048 2075 2049 return ret; 2076 2050 }
+5
drivers/gpu/drm/stm/ltdc.h
··· 40 40 ktime_t last_timestamp; 41 41 }; 42 42 43 + struct ltdc_plat_data { 44 + int pad_max_freq_hz; /* max frequency supported by pad */ 45 + }; 46 + 43 47 struct ltdc_device { 44 48 void __iomem *regs; 45 49 struct regmap *regmap; 46 50 struct clk *pixel_clk; /* lcd pixel clock */ 51 + struct clk *bus_clk; /* bus clock */ 47 52 struct mutex err_lock; /* protecting error_status */ 48 53 struct ltdc_caps caps; 49 54 u32 irq_status;