1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2008 Advanced Micro Devices, Inc.
3*4882a593Smuzhiyun * Copyright 2008 Red Hat Inc.
4*4882a593Smuzhiyun * Copyright 2009 Christian König.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
7*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
8*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
9*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
11*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
14*4882a593Smuzhiyun * all copies or substantial portions of the Software.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*4882a593Smuzhiyun * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*4882a593Smuzhiyun * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*4882a593Smuzhiyun * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*4882a593Smuzhiyun * OTHER DEALINGS IN THE SOFTWARE.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * Authors: Christian König
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun #include <linux/hdmi.h>
27*4882a593Smuzhiyun #include <linux/gcd.h>
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #include <drm/amdgpu_drm.h>
30*4882a593Smuzhiyun #include "amdgpu.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun static const struct amdgpu_afmt_acr amdgpu_afmt_predefined_acr[] = {
33*4882a593Smuzhiyun /* 32kHz 44.1kHz 48kHz */
34*4882a593Smuzhiyun /* Clock N CTS N CTS N CTS */
35*4882a593Smuzhiyun { 25175, 4096, 25175, 28224, 125875, 6144, 25175 }, /* 25,20/1.001 MHz */
36*4882a593Smuzhiyun { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */
37*4882a593Smuzhiyun { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */
38*4882a593Smuzhiyun { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */
39*4882a593Smuzhiyun { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */
40*4882a593Smuzhiyun { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */
41*4882a593Smuzhiyun { 74176, 4096, 74176, 5733, 75335, 6144, 74176 }, /* 74.25/1.001 MHz */
42*4882a593Smuzhiyun { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */
43*4882a593Smuzhiyun { 148352, 4096, 148352, 5733, 150670, 6144, 148352 }, /* 148.50/1.001 MHz */
44*4882a593Smuzhiyun { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /*
49*4882a593Smuzhiyun * calculate CTS and N values if they are not found in the table
50*4882a593Smuzhiyun */
amdgpu_afmt_calc_cts(uint32_t clock,int * CTS,int * N,int freq)51*4882a593Smuzhiyun static void amdgpu_afmt_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun int n, cts;
54*4882a593Smuzhiyun unsigned long div, mul;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Safe, but overly large values */
57*4882a593Smuzhiyun n = 128 * freq;
58*4882a593Smuzhiyun cts = clock * 1000;
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* Smallest valid fraction */
61*4882a593Smuzhiyun div = gcd(n, cts);
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun n /= div;
64*4882a593Smuzhiyun cts /= div;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun * The optimal N is 128*freq/1000. Calculate the closest larger
68*4882a593Smuzhiyun * value that doesn't truncate any bits.
69*4882a593Smuzhiyun */
70*4882a593Smuzhiyun mul = ((128*freq/1000) + (n-1))/n;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun n *= mul;
73*4882a593Smuzhiyun cts *= mul;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /* Check that we are in spec (not always possible) */
76*4882a593Smuzhiyun if (n < (128*freq/1500))
77*4882a593Smuzhiyun pr_warn("Calculated ACR N value is too small. You may experience audio problems.\n");
78*4882a593Smuzhiyun if (n > (128*freq/300))
79*4882a593Smuzhiyun pr_warn("Calculated ACR N value is too large. You may experience audio problems.\n");
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun *N = n;
82*4882a593Smuzhiyun *CTS = cts;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
85*4882a593Smuzhiyun *N, *CTS, freq);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
amdgpu_afmt_acr(uint32_t clock)88*4882a593Smuzhiyun struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun struct amdgpu_afmt_acr res;
91*4882a593Smuzhiyun u8 i;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /* Precalculated values for common clocks */
94*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(amdgpu_afmt_predefined_acr); i++) {
95*4882a593Smuzhiyun if (amdgpu_afmt_predefined_acr[i].clock == clock)
96*4882a593Smuzhiyun return amdgpu_afmt_predefined_acr[i];
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* And odd clocks get manually calculated */
100*4882a593Smuzhiyun amdgpu_afmt_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
101*4882a593Smuzhiyun amdgpu_afmt_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
102*4882a593Smuzhiyun amdgpu_afmt_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun return res;
105*4882a593Smuzhiyun }
106