1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/hdmi.h>
27#include <linux/gcd.h>
28#include <drm/drmP.h>
29#include <drm/amdgpu_drm.h>
30#include "amdgpu.h"
31
32static const struct amdgpu_afmt_acr amdgpu_afmt_predefined_acr[] = {
33
34
35 { 25175, 4096, 25175, 28224, 125875, 6144, 25175 },
36 { 25200, 4096, 25200, 6272, 28000, 6144, 25200 },
37 { 27000, 4096, 27000, 6272, 30000, 6144, 27000 },
38 { 27027, 4096, 27027, 6272, 30030, 6144, 27027 },
39 { 54000, 4096, 54000, 6272, 60000, 6144, 54000 },
40 { 54054, 4096, 54054, 6272, 60060, 6144, 54054 },
41 { 74176, 4096, 74176, 5733, 75335, 6144, 74176 },
42 { 74250, 4096, 74250, 6272, 82500, 6144, 74250 },
43 { 148352, 4096, 148352, 5733, 150670, 6144, 148352 },
44 { 148500, 4096, 148500, 6272, 165000, 6144, 148500 },
45};
46
47
48
49
50
51static void amdgpu_afmt_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
52{
53 int n, cts;
54 unsigned long div, mul;
55
56
57 n = 128 * freq;
58 cts = clock * 1000;
59
60
61 div = gcd(n, cts);
62
63 n /= div;
64 cts /= div;
65
66
67
68
69
70 mul = ((128*freq/1000) + (n-1))/n;
71
72 n *= mul;
73 cts *= mul;
74
75
76 if (n < (128*freq/1500))
77 pr_warn("Calculated ACR N value is too small. You may experience audio problems.\n");
78 if (n > (128*freq/300))
79 pr_warn("Calculated ACR N value is too large. You may experience audio problems.\n");
80
81 *N = n;
82 *CTS = cts;
83
84 DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
85 *N, *CTS, freq);
86}
87
88struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock)
89{
90 struct amdgpu_afmt_acr res;
91 u8 i;
92
93
94 for (i = 0; i < ARRAY_SIZE(amdgpu_afmt_predefined_acr); i++) {
95 if (amdgpu_afmt_predefined_acr[i].clock == clock)
96 return amdgpu_afmt_predefined_acr[i];
97 }
98
99
100 amdgpu_afmt_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
101 amdgpu_afmt_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
102 amdgpu_afmt_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
103
104 return res;
105}
106