@@ -456,6 +456,8 @@ static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
456456 int i , ret ;
457457 u8 val ;
458458
459+ phy -> cur_cfg = cfg ;
460+
459461 /* HDMI PHY init */
460462 writeb (REG33_FIX_DA , phy -> regs + PHY_REG (33 ));
461463
@@ -521,18 +523,9 @@ static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned
521523 /* pll_div_regs 3-6 are fixed and pre-defined already */
522524}
523525
524- static u32 fsl_samsung_hdmi_phy_get_closest_rate (unsigned long rate ,
525- u32 int_div_clk , u32 frac_div_clk )
526- {
527- /* Calculate the absolute value of the differences and return whichever is closest */
528- if (abs ((long )rate - (long )int_div_clk ) < abs ((long )(rate - (long )frac_div_clk )))
529- return int_div_clk ;
530-
531- return frac_div_clk ;
532- }
533-
534- static long fsl_samsung_hdmi_phy_clk_round_rate (struct clk_hw * hw ,
535- unsigned long rate , unsigned long * parent_rate )
526+ static
527+ const struct phy_config * fsl_samsung_hdmi_phy_find_settings (struct fsl_samsung_hdmi_phy * phy ,
528+ unsigned long rate )
536529{
537530 const struct phy_config * fract_div_phy ;
538531 u32 int_div_clk ;
@@ -541,83 +534,66 @@ static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw,
541534
542535 /* If the clock is out of range return error instead of searching */
543536 if (rate > 297000000 || rate < 22250000 )
544- return - EINVAL ;
537+ return NULL ;
545538
546539 /* Search the fractional divider lookup table */
547540 fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate (rate );
541+ if (fract_div_phy -> pixclk == rate ) {
542+ dev_dbg (phy -> dev , "fractional divider match = %u\n" , fract_div_phy -> pixclk );
543+ return fract_div_phy ;
544+ }
548545
549- /* If the rate is an exact match, return that value */
550- if (rate == fract_div_phy -> pixclk )
551- return fract_div_phy -> pixclk ;
552-
553- /* If the exact match isn't found, calculate the integer divider */
546+ /* Calculate the integer divider */
554547 int_div_clk = fsl_samsung_hdmi_phy_find_pms (rate , & p , & m , & s );
548+ fsl_samsung_hdmi_calculate_phy (& calculated_phy_pll_cfg , int_div_clk , p , m , s );
549+ if (int_div_clk == rate ) {
550+ dev_dbg (phy -> dev , "integer divider match = %u\n" , calculated_phy_pll_cfg .pixclk );
551+ return & calculated_phy_pll_cfg ;
552+ }
555553
556- /* If the int_div_clk rate is an exact match, return that value */
557- if (int_div_clk == rate )
558- return int_div_clk ;
554+ /* Calculate the absolute value of the differences and return whichever is closest */
555+ if (abs ((long )rate - (long )int_div_clk ) <
556+ abs ((long )rate - (long )fract_div_phy -> pixclk )) {
557+ dev_dbg (phy -> dev , "integer divider = %u\n" , calculated_phy_pll_cfg .pixclk );
558+ return & calculated_phy_pll_cfg ;
559+ }
559560
560- /* If neither rate is an exact match, use the value from the LUT */
561- return fract_div_phy -> pixclk ;
562- }
561+ dev_dbg (phy -> dev , "fractional divider = %u\n" , phy -> cur_cfg -> pixclk );
563562
564- static int phy_use_fract_div (struct fsl_samsung_hdmi_phy * phy , const struct phy_config * fract_div_phy )
565- {
566- phy -> cur_cfg = fract_div_phy ;
567- dev_dbg (phy -> dev , "fsl_samsung_hdmi_phy: using fractional divider rate = %u\n" ,
568- phy -> cur_cfg -> pixclk );
569- return fsl_samsung_hdmi_phy_configure (phy , phy -> cur_cfg );
563+ return fract_div_phy ;
570564}
571565
572- static int phy_use_integer_div (struct fsl_samsung_hdmi_phy * phy ,
573- const struct phy_config * int_div_clk )
566+ static long fsl_samsung_hdmi_phy_clk_round_rate (struct clk_hw * hw ,
567+ unsigned long rate , unsigned long * parent_rate )
574568{
575- phy -> cur_cfg = & calculated_phy_pll_cfg ;
576- dev_dbg (phy -> dev , "fsl_samsung_hdmi_phy: integer divider rate = %u\n" ,
577- phy -> cur_cfg -> pixclk );
578- return fsl_samsung_hdmi_phy_configure (phy , phy -> cur_cfg );
569+ struct fsl_samsung_hdmi_phy * phy = to_fsl_samsung_hdmi_phy (hw );
570+ const struct phy_config * target_settings = fsl_samsung_hdmi_phy_find_settings (phy , rate );
571+
572+ if (target_settings == NULL )
573+ return - EINVAL ;
574+
575+ dev_dbg (phy -> dev , "round_rate, closest rate = %u\n" , target_settings -> pixclk );
576+ return target_settings -> pixclk ;
579577}
580578
581- static int phy_clk_set_rate (struct clk_hw * hw ,
579+ static int fsl_samsung_hdmi_phy_clk_set_rate (struct clk_hw * hw ,
582580 unsigned long rate , unsigned long parent_rate )
583581{
584582 struct fsl_samsung_hdmi_phy * phy = to_fsl_samsung_hdmi_phy (hw );
585- const struct phy_config * fract_div_phy ;
586- u32 int_div_clk ;
587- u16 m ;
588- u8 p , s ;
589-
590- /* Search the fractional divider lookup table */
591- fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate (rate );
583+ const struct phy_config * target_settings = fsl_samsung_hdmi_phy_find_settings (phy , rate );
592584
593- /* If the rate is an exact match, use that value */
594- if (fract_div_phy -> pixclk == rate )
595- return phy_use_fract_div (phy , fract_div_phy );
585+ if (target_settings == NULL )
586+ return - EINVAL ;
596587
597- /*
598- * If the rate from the fractional divider is not exact, check the integer divider,
599- * and use it if that value is an exact match.
600- */
601- int_div_clk = fsl_samsung_hdmi_phy_find_pms (rate , & p , & m , & s );
602- fsl_samsung_hdmi_calculate_phy (& calculated_phy_pll_cfg , int_div_clk , p , m , s );
603- if (int_div_clk == rate )
604- return phy_use_integer_div (phy , & calculated_phy_pll_cfg );
588+ dev_dbg (phy -> dev , "set_rate, closest rate = %u\n" , target_settings -> pixclk );
605589
606- /*
607- * Compare the difference between the integer clock and the fractional clock against
608- * the desired clock and which whichever is closest.
609- */
610- if (fsl_samsung_hdmi_phy_get_closest_rate (rate , int_div_clk ,
611- fract_div_phy -> pixclk ) == fract_div_phy -> pixclk )
612- return phy_use_fract_div (phy , fract_div_phy );
613- else
614- return phy_use_integer_div (phy , & calculated_phy_pll_cfg );
590+ return fsl_samsung_hdmi_phy_configure (phy , target_settings );
615591}
616592
617593static const struct clk_ops phy_clk_ops = {
618594 .recalc_rate = phy_clk_recalc_rate ,
619595 .round_rate = fsl_samsung_hdmi_phy_clk_round_rate ,
620- .set_rate = phy_clk_set_rate ,
596+ .set_rate = fsl_samsung_hdmi_phy_clk_set_rate ,
621597};
622598
623599static int phy_clk_register (struct fsl_samsung_hdmi_phy * phy )
0 commit comments