@@ -456,6 +456,8 @@ static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
456
456
int i , ret ;
457
457
u8 val ;
458
458
459
+ phy -> cur_cfg = cfg ;
460
+
459
461
/* HDMI PHY init */
460
462
writeb (REG33_FIX_DA , phy -> regs + PHY_REG (33 ));
461
463
@@ -521,18 +523,9 @@ static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned
521
523
/* pll_div_regs 3-6 are fixed and pre-defined already */
522
524
}
523
525
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 )
536
529
{
537
530
const struct phy_config * fract_div_phy ;
538
531
u32 int_div_clk ;
@@ -541,83 +534,66 @@ static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw,
541
534
542
535
/* If the clock is out of range return error instead of searching */
543
536
if (rate > 297000000 || rate < 22250000 )
544
- return - EINVAL ;
537
+ return NULL ;
545
538
546
539
/* Search the fractional divider lookup table */
547
540
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
+ }
548
545
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 */
554
547
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
+ }
555
553
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
+ }
559
560
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 );
563
562
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 ;
570
564
}
571
565
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 )
574
568
{
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 ;
579
577
}
580
578
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 ,
582
580
unsigned long rate , unsigned long parent_rate )
583
581
{
584
582
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 );
592
584
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 ;
596
587
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 );
605
589
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 );
615
591
}
616
592
617
593
static const struct clk_ops phy_clk_ops = {
618
594
.recalc_rate = phy_clk_recalc_rate ,
619
595
.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 ,
621
597
};
622
598
623
599
static int phy_clk_register (struct fsl_samsung_hdmi_phy * phy )
0 commit comments