Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2008 Advanced Micro Devices, Inc.
0003  * Copyright 2008 Red Hat Inc.
0004  * Copyright 2009 Christian König.
0005  *
0006  * Permission is hereby granted, free of charge, to any person obtaining a
0007  * copy of this software and associated documentation files (the "Software"),
0008  * to deal in the Software without restriction, including without limitation
0009  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010  * and/or sell copies of the Software, and to permit persons to whom the
0011  * Software is furnished to do so, subject to the following conditions:
0012  *
0013  * The above copyright notice and this permission notice shall be included in
0014  * all copies or substantial portions of the Software.
0015  *
0016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0018  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0019  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0020  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0021  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0022  * OTHER DEALINGS IN THE SOFTWARE.
0023  *
0024  * Authors: Christian König
0025  */
0026 #include <linux/hdmi.h>
0027 #include <linux/gcd.h>
0028 
0029 #include <drm/amdgpu_drm.h>
0030 #include "amdgpu.h"
0031 
0032 static const struct amdgpu_afmt_acr amdgpu_afmt_predefined_acr[] = {
0033     /*       32kHz    44.1kHz   48kHz    */
0034     /* Clock      N     CTS      N     CTS      N     CTS */
0035     {  25175,  4096,  25175, 28224, 125875,  6144,  25175 }, /*  25,20/1.001 MHz */
0036     {  25200,  4096,  25200,  6272,  28000,  6144,  25200 }, /*  25.20       MHz */
0037     {  27000,  4096,  27000,  6272,  30000,  6144,  27000 }, /*  27.00       MHz */
0038     {  27027,  4096,  27027,  6272,  30030,  6144,  27027 }, /*  27.00*1.001 MHz */
0039     {  54000,  4096,  54000,  6272,  60000,  6144,  54000 }, /*  54.00       MHz */
0040     {  54054,  4096,  54054,  6272,  60060,  6144,  54054 }, /*  54.00*1.001 MHz */
0041     {  74176,  4096,  74176,  5733,  75335,  6144,  74176 }, /*  74.25/1.001 MHz */
0042     {  74250,  4096,  74250,  6272,  82500,  6144,  74250 }, /*  74.25       MHz */
0043     { 148352,  4096, 148352,  5733, 150670,  6144, 148352 }, /* 148.50/1.001 MHz */
0044     { 148500,  4096, 148500,  6272, 165000,  6144, 148500 }, /* 148.50       MHz */
0045 };
0046 
0047 
0048 /*
0049  * calculate CTS and N values if they are not found in the table
0050  */
0051 static void amdgpu_afmt_calc_cts(uint32_t clock, int *CTS, int *N, int freq)
0052 {
0053     int n, cts;
0054     unsigned long div, mul;
0055 
0056     /* Safe, but overly large values */
0057     n = 128 * freq;
0058     cts = clock * 1000;
0059 
0060     /* Smallest valid fraction */
0061     div = gcd(n, cts);
0062 
0063     n /= div;
0064     cts /= div;
0065 
0066     /*
0067      * The optimal N is 128*freq/1000. Calculate the closest larger
0068      * value that doesn't truncate any bits.
0069      */
0070     mul = ((128*freq/1000) + (n-1))/n;
0071 
0072     n *= mul;
0073     cts *= mul;
0074 
0075     /* Check that we are in spec (not always possible) */
0076     if (n < (128*freq/1500))
0077         pr_warn("Calculated ACR N value is too small. You may experience audio problems.\n");
0078     if (n > (128*freq/300))
0079         pr_warn("Calculated ACR N value is too large. You may experience audio problems.\n");
0080 
0081     *N = n;
0082     *CTS = cts;
0083 
0084     DRM_DEBUG("Calculated ACR timing N=%d CTS=%d for frequency %d\n",
0085           *N, *CTS, freq);
0086 }
0087 
0088 struct amdgpu_afmt_acr amdgpu_afmt_acr(uint32_t clock)
0089 {
0090     struct amdgpu_afmt_acr res;
0091     u8 i;
0092 
0093     /* Precalculated values for common clocks */
0094     for (i = 0; i < ARRAY_SIZE(amdgpu_afmt_predefined_acr); i++) {
0095         if (amdgpu_afmt_predefined_acr[i].clock == clock)
0096             return amdgpu_afmt_predefined_acr[i];
0097     }
0098 
0099     /* And odd clocks get manually calculated */
0100     amdgpu_afmt_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
0101     amdgpu_afmt_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
0102     amdgpu_afmt_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
0103 
0104     return res;
0105 }