xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/omapdrm/dss/hdmi_common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun #define DSS_SUBSYS_NAME "HDMI"
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/kernel.h>
6*4882a593Smuzhiyun #include <linux/err.h>
7*4882a593Smuzhiyun #include <linux/of.h>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include "omapdss.h"
10*4882a593Smuzhiyun #include "hdmi.h"
11*4882a593Smuzhiyun 
hdmi_parse_lanes_of(struct platform_device * pdev,struct device_node * ep,struct hdmi_phy_data * phy)12*4882a593Smuzhiyun int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
13*4882a593Smuzhiyun 	struct hdmi_phy_data *phy)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct property *prop;
16*4882a593Smuzhiyun 	int r, len;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	prop = of_find_property(ep, "lanes", &len);
19*4882a593Smuzhiyun 	if (prop) {
20*4882a593Smuzhiyun 		u32 lanes[8];
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun 		if (len / sizeof(u32) != ARRAY_SIZE(lanes)) {
23*4882a593Smuzhiyun 			dev_err(&pdev->dev, "bad number of lanes\n");
24*4882a593Smuzhiyun 			return -EINVAL;
25*4882a593Smuzhiyun 		}
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 		r = of_property_read_u32_array(ep, "lanes", lanes,
28*4882a593Smuzhiyun 			ARRAY_SIZE(lanes));
29*4882a593Smuzhiyun 		if (r) {
30*4882a593Smuzhiyun 			dev_err(&pdev->dev, "failed to read lane data\n");
31*4882a593Smuzhiyun 			return r;
32*4882a593Smuzhiyun 		}
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 		r = hdmi_phy_parse_lanes(phy, lanes);
35*4882a593Smuzhiyun 		if (r) {
36*4882a593Smuzhiyun 			dev_err(&pdev->dev, "failed to parse lane data\n");
37*4882a593Smuzhiyun 			return r;
38*4882a593Smuzhiyun 		}
39*4882a593Smuzhiyun 	} else {
40*4882a593Smuzhiyun 		static const u32 default_lanes[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 		r = hdmi_phy_parse_lanes(phy, default_lanes);
43*4882a593Smuzhiyun 		if (WARN_ON(r)) {
44*4882a593Smuzhiyun 			dev_err(&pdev->dev, "failed to parse lane data\n");
45*4882a593Smuzhiyun 			return r;
46*4882a593Smuzhiyun 		}
47*4882a593Smuzhiyun 	}
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	return 0;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
hdmi_compute_acr(u32 pclk,u32 sample_freq,u32 * n,u32 * cts)52*4882a593Smuzhiyun int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	u32 deep_color;
55*4882a593Smuzhiyun 	bool deep_color_correct = false;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	if (n == NULL || cts == NULL)
58*4882a593Smuzhiyun 		return -EINVAL;
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	/* TODO: When implemented, query deep color mode here. */
61*4882a593Smuzhiyun 	deep_color = 100;
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/*
64*4882a593Smuzhiyun 	 * When using deep color, the default N value (as in the HDMI
65*4882a593Smuzhiyun 	 * specification) yields to an non-integer CTS. Hence, we
66*4882a593Smuzhiyun 	 * modify it while keeping the restrictions described in
67*4882a593Smuzhiyun 	 * section 7.2.1 of the HDMI 1.4a specification.
68*4882a593Smuzhiyun 	 */
69*4882a593Smuzhiyun 	switch (sample_freq) {
70*4882a593Smuzhiyun 	case 32000:
71*4882a593Smuzhiyun 	case 48000:
72*4882a593Smuzhiyun 	case 96000:
73*4882a593Smuzhiyun 	case 192000:
74*4882a593Smuzhiyun 		if (deep_color == 125)
75*4882a593Smuzhiyun 			if (pclk == 27027000 || pclk == 74250000)
76*4882a593Smuzhiyun 				deep_color_correct = true;
77*4882a593Smuzhiyun 		if (deep_color == 150)
78*4882a593Smuzhiyun 			if (pclk == 27027000)
79*4882a593Smuzhiyun 				deep_color_correct = true;
80*4882a593Smuzhiyun 		break;
81*4882a593Smuzhiyun 	case 44100:
82*4882a593Smuzhiyun 	case 88200:
83*4882a593Smuzhiyun 	case 176400:
84*4882a593Smuzhiyun 		if (deep_color == 125)
85*4882a593Smuzhiyun 			if (pclk == 27027000)
86*4882a593Smuzhiyun 				deep_color_correct = true;
87*4882a593Smuzhiyun 		break;
88*4882a593Smuzhiyun 	default:
89*4882a593Smuzhiyun 		return -EINVAL;
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	if (deep_color_correct) {
93*4882a593Smuzhiyun 		switch (sample_freq) {
94*4882a593Smuzhiyun 		case 32000:
95*4882a593Smuzhiyun 			*n = 8192;
96*4882a593Smuzhiyun 			break;
97*4882a593Smuzhiyun 		case 44100:
98*4882a593Smuzhiyun 			*n = 12544;
99*4882a593Smuzhiyun 			break;
100*4882a593Smuzhiyun 		case 48000:
101*4882a593Smuzhiyun 			*n = 8192;
102*4882a593Smuzhiyun 			break;
103*4882a593Smuzhiyun 		case 88200:
104*4882a593Smuzhiyun 			*n = 25088;
105*4882a593Smuzhiyun 			break;
106*4882a593Smuzhiyun 		case 96000:
107*4882a593Smuzhiyun 			*n = 16384;
108*4882a593Smuzhiyun 			break;
109*4882a593Smuzhiyun 		case 176400:
110*4882a593Smuzhiyun 			*n = 50176;
111*4882a593Smuzhiyun 			break;
112*4882a593Smuzhiyun 		case 192000:
113*4882a593Smuzhiyun 			*n = 32768;
114*4882a593Smuzhiyun 			break;
115*4882a593Smuzhiyun 		default:
116*4882a593Smuzhiyun 			return -EINVAL;
117*4882a593Smuzhiyun 		}
118*4882a593Smuzhiyun 	} else {
119*4882a593Smuzhiyun 		switch (sample_freq) {
120*4882a593Smuzhiyun 		case 32000:
121*4882a593Smuzhiyun 			*n = 4096;
122*4882a593Smuzhiyun 			break;
123*4882a593Smuzhiyun 		case 44100:
124*4882a593Smuzhiyun 			*n = 6272;
125*4882a593Smuzhiyun 			break;
126*4882a593Smuzhiyun 		case 48000:
127*4882a593Smuzhiyun 			*n = 6144;
128*4882a593Smuzhiyun 			break;
129*4882a593Smuzhiyun 		case 88200:
130*4882a593Smuzhiyun 			*n = 12544;
131*4882a593Smuzhiyun 			break;
132*4882a593Smuzhiyun 		case 96000:
133*4882a593Smuzhiyun 			*n = 12288;
134*4882a593Smuzhiyun 			break;
135*4882a593Smuzhiyun 		case 176400:
136*4882a593Smuzhiyun 			*n = 25088;
137*4882a593Smuzhiyun 			break;
138*4882a593Smuzhiyun 		case 192000:
139*4882a593Smuzhiyun 			*n = 24576;
140*4882a593Smuzhiyun 			break;
141*4882a593Smuzhiyun 		default:
142*4882a593Smuzhiyun 			return -EINVAL;
143*4882a593Smuzhiyun 		}
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 	/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
146*4882a593Smuzhiyun 	*cts = (pclk/1000) * (*n / 128) * deep_color / (sample_freq / 10);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	return 0;
149*4882a593Smuzhiyun }
150