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