19
19
#include "fsl_asrc.h"
20
20
21
21
#define IDEAL_RATIO_DECIMAL_DEPTH 26
22
+ #define DIVIDER_NUM 64
22
23
23
24
#define pair_err (fmt , ...) \
24
25
dev_err(&asrc->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__)
@@ -101,6 +102,55 @@ static unsigned char clk_map_imx8qxp[2][ASRC_CLK_MAP_LEN] = {
101
102
},
102
103
};
103
104
105
+ /*
106
+ * According to RM, the divider range is 1 ~ 8,
107
+ * prescaler is power of 2 from 1 ~ 128.
108
+ */
109
+ static int asrc_clk_divider [DIVIDER_NUM ] = {
110
+ 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 , /* divider = 1 */
111
+ 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 , /* divider = 2 */
112
+ 3 , 6 , 12 , 24 , 48 , 96 , 192 , 384 , /* divider = 3 */
113
+ 4 , 8 , 16 , 32 , 64 , 128 , 256 , 512 , /* divider = 4 */
114
+ 5 , 10 , 20 , 40 , 80 , 160 , 320 , 640 , /* divider = 5 */
115
+ 6 , 12 , 24 , 48 , 96 , 192 , 384 , 768 , /* divider = 6 */
116
+ 7 , 14 , 28 , 56 , 112 , 224 , 448 , 896 , /* divider = 7 */
117
+ 8 , 16 , 32 , 64 , 128 , 256 , 512 , 1024 , /* divider = 8 */
118
+ };
119
+
120
+ /*
121
+ * Check if the divider is available for internal ratio mode
122
+ */
123
+ static bool fsl_asrc_divider_avail (int clk_rate , int rate , int * div )
124
+ {
125
+ u32 rem , i ;
126
+ u64 n ;
127
+
128
+ if (div )
129
+ * div = 0 ;
130
+
131
+ if (clk_rate == 0 || rate == 0 )
132
+ return false;
133
+
134
+ n = clk_rate ;
135
+ rem = do_div (n , rate );
136
+
137
+ if (div )
138
+ * div = n ;
139
+
140
+ if (rem != 0 )
141
+ return false;
142
+
143
+ for (i = 0 ; i < DIVIDER_NUM ; i ++ ) {
144
+ if (n == asrc_clk_divider [i ])
145
+ break ;
146
+ }
147
+
148
+ if (i == DIVIDER_NUM )
149
+ return false;
150
+
151
+ return true;
152
+ }
153
+
104
154
/**
105
155
* fsl_asrc_sel_proc - Select the pre-processing and post-processing options
106
156
* @inrate: input sample rate
@@ -330,12 +380,12 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
330
380
enum asrc_word_width input_word_width ;
331
381
enum asrc_word_width output_word_width ;
332
382
u32 inrate , outrate , indiv , outdiv ;
333
- u32 clk_index [2 ], div [2 ], rem [ 2 ] ;
383
+ u32 clk_index [2 ], div [2 ];
334
384
u64 clk_rate ;
335
385
int in , out , channels ;
336
386
int pre_proc , post_proc ;
337
387
struct clk * clk ;
338
- bool ideal ;
388
+ bool ideal , div_avail ;
339
389
340
390
if (!config ) {
341
391
pair_err ("invalid pair config\n" );
@@ -415,8 +465,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
415
465
clk = asrc_priv -> asrck_clk [clk_index [ideal ? OUT : IN ]];
416
466
417
467
clk_rate = clk_get_rate (clk );
418
- rem [IN ] = do_div (clk_rate , inrate );
419
- div [IN ] = (u32 )clk_rate ;
468
+ div_avail = fsl_asrc_divider_avail (clk_rate , inrate , & div [IN ]);
420
469
421
470
/*
422
471
* The divider range is [1, 1024], defined by the hardware. For non-
@@ -425,7 +474,7 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
425
474
* only result in different converting speeds. So remainder does not
426
475
* matter, as long as we keep the divider within its valid range.
427
476
*/
428
- if (div [IN ] == 0 || (!ideal && ( div [ IN ] > 1024 || rem [ IN ] != 0 ) )) {
477
+ if (div [IN ] == 0 || (!ideal && ! div_avail )) {
429
478
pair_err ("failed to support input sample rate %dHz by asrck_%x\n" ,
430
479
inrate , clk_index [ideal ? OUT : IN ]);
431
480
return - EINVAL ;
@@ -436,13 +485,12 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
436
485
clk = asrc_priv -> asrck_clk [clk_index [OUT ]];
437
486
clk_rate = clk_get_rate (clk );
438
487
if (ideal && use_ideal_rate )
439
- rem [ OUT ] = do_div (clk_rate , IDEAL_RATIO_RATE );
488
+ div_avail = fsl_asrc_divider_avail (clk_rate , IDEAL_RATIO_RATE , & div [ OUT ] );
440
489
else
441
- rem [OUT ] = do_div (clk_rate , outrate );
442
- div [OUT ] = clk_rate ;
490
+ div_avail = fsl_asrc_divider_avail (clk_rate , outrate , & div [OUT ]);
443
491
444
492
/* Output divider has the same limitation as the input one */
445
- if (div [OUT ] == 0 || (!ideal && ( div [ OUT ] > 1024 || rem [ OUT ] != 0 ) )) {
493
+ if (div [OUT ] == 0 || (!ideal && ! div_avail )) {
446
494
pair_err ("failed to support output sample rate %dHz by asrck_%x\n" ,
447
495
outrate , clk_index [OUT ]);
448
496
return - EINVAL ;
@@ -621,8 +669,7 @@ static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
621
669
clk_index = asrc_priv -> clk_map [j ][i ];
622
670
clk_rate = clk_get_rate (asrc_priv -> asrck_clk [clk_index ]);
623
671
/* Only match a perfect clock source with no remainder */
624
- if (clk_rate != 0 && (clk_rate / rate [j ]) <= 1024 &&
625
- (clk_rate % rate [j ]) == 0 )
672
+ if (fsl_asrc_divider_avail (clk_rate , rate [j ], NULL ))
626
673
break ;
627
674
}
628
675
0 commit comments