2018-12-07 14:55:31 +01:00
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright ( C ) 2013 NVIDIA Corporation
* Copyright ( C ) 2018 Cadence Design Systems Inc .
*/
# include <linux/errno.h>
# include <linux/export.h>
# include <linux/kernel.h>
# include <linux/time64.h>
# include <linux/phy/phy.h>
# include <linux/phy/phy-mipi-dphy.h>
/*
* Minimum D - PHY timings based on MIPI D - PHY specification . Derived
* from the valid ranges specified in Section 6.9 , Table 14 , Page 41
2021-04-21 04:17:41 +00:00
* of the D - PHY specification ( v1 .2 ) .
2018-12-07 14:55:31 +01:00
*/
int phy_mipi_dphy_get_default_config ( unsigned long pixel_clock ,
unsigned int bpp ,
unsigned int lanes ,
struct phy_configure_opts_mipi_dphy * cfg )
{
unsigned long long hs_clk_rate ;
unsigned long long ui ;
if ( ! cfg )
return - EINVAL ;
hs_clk_rate = pixel_clock * bpp ;
do_div ( hs_clk_rate , lanes ) ;
ui = ALIGN ( PSEC_PER_SEC , hs_clk_rate ) ;
do_div ( ui , hs_clk_rate ) ;
cfg - > clk_miss = 0 ;
cfg - > clk_post = 60000 + 52 * ui ;
2022-01-24 10:40:07 +08:00
cfg - > clk_pre = 8 ;
2018-12-07 14:55:31 +01:00
cfg - > clk_prepare = 38000 ;
cfg - > clk_settle = 95000 ;
cfg - > clk_term_en = 0 ;
cfg - > clk_trail = 60000 ;
cfg - > clk_zero = 262000 ;
cfg - > d_term_en = 0 ;
cfg - > eot = 0 ;
cfg - > hs_exit = 100000 ;
cfg - > hs_prepare = 40000 + 4 * ui ;
cfg - > hs_zero = 105000 + 6 * ui ;
cfg - > hs_settle = 85000 + 6 * ui ;
cfg - > hs_skip = 40000 ;
/*
* The MIPI D - PHY specification ( Section 6.9 , v1 .2 , Table 14 , Page 40 )
* contains this formula as :
*
* T_HS - TRAIL = max ( n * 8 * ui , 60 + n * 4 * ui )
*
* where n = 1 for forward - direction HS mode and n = 4 for reverse -
* direction HS mode . There ' s only one setting and this function does
* not parameterize on anything other that ui , so this code will
* assumes that reverse - direction HS mode is supported and uses n = 4.
*/
cfg - > hs_trail = max ( 4 * 8 * ui , 60000 + 4 * 4 * ui ) ;
2019-01-21 16:45:47 +01:00
cfg - > init = 100 ;
phy: dphy: Correct lpx parameter and its derivatives(ta_{get,go,sure})
According to the comment of the function phy_mipi_dphy_get_default_config(),
it uses minimum D-PHY timings based on MIPI D-PHY specification. They are
derived from the valid ranges specified in Section 6.9, Table 14, Page 41
of the D-PHY specification (v1.2). The table 14 explicitly mentions that
the minimum T-LPX parameter is 50 nanoseconds and the minimum TA-SURE
parameter is T-LPX nanoseconds. Likewise, the kernel doc of the 'lpx' and
'ta_sure' members of struct phy_configure_opts_mipi_dphy mentions that
the minimum values are 50000 picoseconds and @lpx picoseconds respectively.
Also, the function phy_mipi_dphy_config_validate() checks if cfg->lpx is
less than 50000 picoseconds and if cfg->ta_sure is less than cfg->lpx,
which hints the same minimum values.
Without this patch, the function phy_mipi_dphy_get_default_config()
wrongly sets cfg->lpx to 60000 picoseconds and cfg->ta_sure to 2 * cfg->lpx.
So, let's correct them to 50000 picoseconds and cfg->lpx respectively.
Note that I've only tested the patch with RM67191 DSI panel on i.MX8mq EVK.
Help is needed to test with other i.MX8mq, Meson and Rockchip platforms,
as I don't have the hardwares.
Fixes: dddc97e82303 ("phy: dphy: Add configuration helpers")
Cc: Andrzej Hajda <andrzej.hajda@intel.com>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Guido Günther <agx@sigxcpu.org>
Signed-off-by: Liu Ying <victor.liu@nxp.com>
Link: https://lore.kernel.org/r/20220216071257.1647703-1-victor.liu@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
2022-02-16 15:12:57 +08:00
cfg - > lpx = 50000 ;
2018-12-07 14:55:31 +01:00
cfg - > ta_get = 5 * cfg - > lpx ;
cfg - > ta_go = 4 * cfg - > lpx ;
phy: dphy: Correct lpx parameter and its derivatives(ta_{get,go,sure})
According to the comment of the function phy_mipi_dphy_get_default_config(),
it uses minimum D-PHY timings based on MIPI D-PHY specification. They are
derived from the valid ranges specified in Section 6.9, Table 14, Page 41
of the D-PHY specification (v1.2). The table 14 explicitly mentions that
the minimum T-LPX parameter is 50 nanoseconds and the minimum TA-SURE
parameter is T-LPX nanoseconds. Likewise, the kernel doc of the 'lpx' and
'ta_sure' members of struct phy_configure_opts_mipi_dphy mentions that
the minimum values are 50000 picoseconds and @lpx picoseconds respectively.
Also, the function phy_mipi_dphy_config_validate() checks if cfg->lpx is
less than 50000 picoseconds and if cfg->ta_sure is less than cfg->lpx,
which hints the same minimum values.
Without this patch, the function phy_mipi_dphy_get_default_config()
wrongly sets cfg->lpx to 60000 picoseconds and cfg->ta_sure to 2 * cfg->lpx.
So, let's correct them to 50000 picoseconds and cfg->lpx respectively.
Note that I've only tested the patch with RM67191 DSI panel on i.MX8mq EVK.
Help is needed to test with other i.MX8mq, Meson and Rockchip platforms,
as I don't have the hardwares.
Fixes: dddc97e82303 ("phy: dphy: Add configuration helpers")
Cc: Andrzej Hajda <andrzej.hajda@intel.com>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Cc: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Guido Günther <agx@sigxcpu.org>
Signed-off-by: Liu Ying <victor.liu@nxp.com>
Link: https://lore.kernel.org/r/20220216071257.1647703-1-victor.liu@nxp.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
2022-02-16 15:12:57 +08:00
cfg - > ta_sure = cfg - > lpx ;
2019-01-21 16:45:47 +01:00
cfg - > wakeup = 1000 ;
2018-12-07 14:55:31 +01:00
cfg - > hs_clk_rate = hs_clk_rate ;
cfg - > lanes = lanes ;
return 0 ;
}
EXPORT_SYMBOL ( phy_mipi_dphy_get_default_config ) ;
/*
* Validate D - PHY configuration according to MIPI D - PHY specification
* ( v1 .2 , Section Section 6.9 " Global Operation Timing Parameters " ) .
*/
int phy_mipi_dphy_config_validate ( struct phy_configure_opts_mipi_dphy * cfg )
{
unsigned long long ui ;
if ( ! cfg )
return - EINVAL ;
ui = ALIGN ( PSEC_PER_SEC , cfg - > hs_clk_rate ) ;
do_div ( ui , cfg - > hs_clk_rate ) ;
if ( cfg - > clk_miss > 60000 )
return - EINVAL ;
if ( cfg - > clk_post < ( 60000 + 52 * ui ) )
return - EINVAL ;
2022-01-24 10:40:07 +08:00
if ( cfg - > clk_pre < 8 )
2018-12-07 14:55:31 +01:00
return - EINVAL ;
if ( cfg - > clk_prepare < 38000 | | cfg - > clk_prepare > 95000 )
return - EINVAL ;
if ( cfg - > clk_settle < 95000 | | cfg - > clk_settle > 300000 )
return - EINVAL ;
if ( cfg - > clk_term_en > 38000 )
return - EINVAL ;
if ( cfg - > clk_trail < 60000 )
return - EINVAL ;
if ( ( cfg - > clk_prepare + cfg - > clk_zero ) < 300000 )
return - EINVAL ;
if ( cfg - > d_term_en > ( 35000 + 4 * ui ) )
return - EINVAL ;
if ( cfg - > eot > ( 105000 + 12 * ui ) )
return - EINVAL ;
if ( cfg - > hs_exit < 100000 )
return - EINVAL ;
if ( cfg - > hs_prepare < ( 40000 + 4 * ui ) | |
cfg - > hs_prepare > ( 85000 + 6 * ui ) )
return - EINVAL ;
if ( ( cfg - > hs_prepare + cfg - > hs_zero ) < ( 145000 + 10 * ui ) )
return - EINVAL ;
if ( ( cfg - > hs_settle < ( 85000 + 6 * ui ) ) | |
( cfg - > hs_settle > ( 145000 + 10 * ui ) ) )
return - EINVAL ;
if ( cfg - > hs_skip < 40000 | | cfg - > hs_skip > ( 55000 + 4 * ui ) )
return - EINVAL ;
if ( cfg - > hs_trail < max ( 8 * ui , 60000 + 4 * ui ) )
return - EINVAL ;
2019-01-21 16:45:47 +01:00
if ( cfg - > init < 100 )
2018-12-07 14:55:31 +01:00
return - EINVAL ;
if ( cfg - > lpx < 50000 )
return - EINVAL ;
if ( cfg - > ta_get ! = ( 5 * cfg - > lpx ) )
return - EINVAL ;
if ( cfg - > ta_go ! = ( 4 * cfg - > lpx ) )
return - EINVAL ;
if ( cfg - > ta_sure < cfg - > lpx | | cfg - > ta_sure > ( 2 * cfg - > lpx ) )
return - EINVAL ;
2019-01-21 16:45:47 +01:00
if ( cfg - > wakeup < 1000 )
2018-12-07 14:55:31 +01:00
return - EINVAL ;
return 0 ;
}
EXPORT_SYMBOL ( phy_mipi_dphy_config_validate ) ;