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

drm: bridge: samsung-dsim: Dynamically configure DPHY timing

The DPHY timings are currently hard coded. Since the input
clock can be variable, the phy timings need to be variable
too. To facilitate this, we need to cache the hs_clock
based on what is generated from the PLL.

The phy_mipi_dphy_get_default_config_for_hsclk function
configures the DPHY timings in pico-seconds, and a small macro
converts those timings into clock cycles based on the hs_clk.

Signed-off-by: Adam Ford <aford173@gmail.com>
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Tested-by: Chen-Yu Tsai <wenst@chromium.org>
Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>
Tested-by: Michael Walle <michael@walle.cc>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
Tested-by: Jagan Teki <jagan@amarulasolutions.com> # imx8mm-icore
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20230526030559.326566-6-aford173@gmail.com

authored by

Adam Ford and committed by
Neil Armstrong
89691775 171b3b1e

+52 -7
+51 -7
drivers/gpu/drm/bridge/samsung-dsim.c
··· 220 220 221 221 #define OLD_SCLK_MIPI_CLK_NAME "pll_clk" 222 222 223 + #define PS_TO_CYCLE(ps, hz) DIV64_U64_ROUND_CLOSEST(((ps) * (hz)), 1000000000000ULL) 224 + 223 225 static const char *const clk_names[5] = { 224 226 "bus_clk", 225 227 "sclk_mipi", ··· 660 658 reg = samsung_dsim_read(dsi, DSIM_STATUS_REG); 661 659 } while ((reg & DSIM_PLL_STABLE) == 0); 662 660 661 + dsi->hs_clock = fout; 662 + 663 663 return fout; 664 664 } 665 665 ··· 709 705 const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; 710 706 const unsigned int *reg_values = driver_data->reg_values; 711 707 u32 reg; 708 + struct phy_configure_opts_mipi_dphy cfg; 709 + int clk_prepare, lpx, clk_zero, clk_post, clk_trail; 710 + int hs_exit, hs_prepare, hs_zero, hs_trail; 711 + unsigned long long byte_clock = dsi->hs_clock / 8; 712 712 713 713 if (driver_data->has_freqband) 714 714 return; 715 715 716 + phy_mipi_dphy_get_default_config_for_hsclk(dsi->hs_clock, 717 + dsi->lanes, &cfg); 718 + 719 + /* 720 + * TODO: 721 + * The tech Applications Processor manuals for i.MX8M Mini, Nano, 722 + * and Plus don't state what the definition of the PHYTIMING 723 + * bits are beyond their address and bit position. 724 + * After reviewing NXP's downstream code, it appears 725 + * that the various PHYTIMING registers take the number 726 + * of cycles and use various dividers on them. This 727 + * calculation does not result in an exact match to the 728 + * downstream code, but it is very close to the values 729 + * generated by their lookup table, and it appears 730 + * to sync at a variety of resolutions. If someone 731 + * can get a more accurate mathematical equation needed 732 + * for these registers, this should be updated. 733 + */ 734 + 735 + lpx = PS_TO_CYCLE(cfg.lpx, byte_clock); 736 + hs_exit = PS_TO_CYCLE(cfg.hs_exit, byte_clock); 737 + clk_prepare = PS_TO_CYCLE(cfg.clk_prepare, byte_clock); 738 + clk_zero = PS_TO_CYCLE(cfg.clk_zero, byte_clock); 739 + clk_post = PS_TO_CYCLE(cfg.clk_post, byte_clock); 740 + clk_trail = PS_TO_CYCLE(cfg.clk_trail, byte_clock); 741 + hs_prepare = PS_TO_CYCLE(cfg.hs_prepare, byte_clock); 742 + hs_zero = PS_TO_CYCLE(cfg.hs_zero, byte_clock); 743 + hs_trail = PS_TO_CYCLE(cfg.hs_trail, byte_clock); 744 + 716 745 /* B D-PHY: D-PHY Master & Slave Analog Block control */ 717 746 reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] | 718 747 reg_values[PHYCTRL_SLEW_UP]; 748 + 719 749 samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg); 720 750 721 751 /* ··· 757 719 * T HS-EXIT: Time that the transmitter drives LP-11 following a HS 758 720 * burst 759 721 */ 760 - reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT]; 722 + 723 + reg = DSIM_PHYTIMING_LPX(lpx) | DSIM_PHYTIMING_HS_EXIT(hs_exit); 724 + 761 725 samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg); 762 726 763 727 /* ··· 775 735 * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after 776 736 * the last payload clock bit of a HS transmission burst 777 737 */ 778 - reg = reg_values[PHYTIMING_CLK_PREPARE] | 779 - reg_values[PHYTIMING_CLK_ZERO] | 780 - reg_values[PHYTIMING_CLK_POST] | 781 - reg_values[PHYTIMING_CLK_TRAIL]; 738 + 739 + reg = DSIM_PHYTIMING1_CLK_PREPARE(clk_prepare) | 740 + DSIM_PHYTIMING1_CLK_ZERO(clk_zero) | 741 + DSIM_PHYTIMING1_CLK_POST(clk_post) | 742 + DSIM_PHYTIMING1_CLK_TRAIL(clk_trail); 782 743 783 744 samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg); 784 745 ··· 792 751 * T HS-TRAIL: Time that the transmitter drives the flipped differential 793 752 * state after last payload data bit of a HS transmission burst 794 753 */ 795 - reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] | 796 - reg_values[PHYTIMING_HS_TRAIL]; 754 + 755 + reg = DSIM_PHYTIMING2_HS_PREPARE(hs_prepare) | 756 + DSIM_PHYTIMING2_HS_ZERO(hs_zero) | 757 + DSIM_PHYTIMING2_HS_TRAIL(hs_trail); 758 + 797 759 samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg); 798 760 } 799 761
+1
include/drm/bridge/samsung-dsim.h
··· 93 93 94 94 u32 pll_clk_rate; 95 95 u32 burst_clk_rate; 96 + u32 hs_clock; 96 97 u32 esc_clk_rate; 97 98 u32 lanes; 98 99 u32 mode_flags;