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