Linux Audio

Check our new training course

Open-source upstreaming

Need help get the support for your hardware in upstream Linux?
Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
  4 */
  5
  6#include <linux/of_gpio.h>
  7#include <linux/phy/phy.h>
  8
  9#include <drm/drm_of.h>
 10#include <drm/drm_print.h>
 11#include <drm/drm_bridge.h>
 12
 13#include "dp_parser.h"
 14#include "dp_reg.h"
 15
 16#define DP_DEFAULT_AHB_OFFSET	0x0000
 17#define DP_DEFAULT_AHB_SIZE	0x0200
 18#define DP_DEFAULT_AUX_OFFSET	0x0200
 19#define DP_DEFAULT_AUX_SIZE	0x0200
 20#define DP_DEFAULT_LINK_OFFSET	0x0400
 21#define DP_DEFAULT_LINK_SIZE	0x0C00
 22#define DP_DEFAULT_P0_OFFSET	0x1000
 23#define DP_DEFAULT_P0_SIZE	0x0400
 24
 25static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len)
 26{
 27	struct resource *res;
 28	void __iomem *base;
 29
 30	base = devm_platform_get_and_ioremap_resource(pdev, idx, &res);
 31	if (!IS_ERR(base))
 32		*len = resource_size(res);
 33
 34	return base;
 35}
 36
 37static int dp_parser_ctrl_res(struct dp_parser *parser)
 38{
 39	struct platform_device *pdev = parser->pdev;
 40	struct dp_io *io = &parser->io;
 41	struct dss_io_data *dss = &io->dp_controller;
 42
 43	dss->ahb.base = dp_ioremap(pdev, 0, &dss->ahb.len);
 44	if (IS_ERR(dss->ahb.base))
 45		return PTR_ERR(dss->ahb.base);
 46
 47	dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len);
 48	if (IS_ERR(dss->aux.base)) {
 49		/*
 50		 * The initial binding had a single reg, but in order to
 51		 * support variation in the sub-region sizes this was split.
 52		 * dp_ioremap() will fail with -EINVAL here if only a single
 53		 * reg is specified, so fill in the sub-region offsets and
 54		 * lengths based on this single region.
 55		 */
 56		if (PTR_ERR(dss->aux.base) == -EINVAL) {
 57			if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) {
 58				DRM_ERROR("legacy memory region not large enough\n");
 59				return -EINVAL;
 60			}
 61
 62			dss->ahb.len = DP_DEFAULT_AHB_SIZE;
 63			dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET;
 64			dss->aux.len = DP_DEFAULT_AUX_SIZE;
 65			dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET;
 66			dss->link.len = DP_DEFAULT_LINK_SIZE;
 67			dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET;
 68			dss->p0.len = DP_DEFAULT_P0_SIZE;
 69		} else {
 70			DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base);
 71			return PTR_ERR(dss->aux.base);
 72		}
 73	} else {
 74		dss->link.base = dp_ioremap(pdev, 2, &dss->link.len);
 75		if (IS_ERR(dss->link.base)) {
 76			DRM_ERROR("unable to remap link region: %pe\n", dss->link.base);
 77			return PTR_ERR(dss->link.base);
 78		}
 79
 80		dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len);
 81		if (IS_ERR(dss->p0.base)) {
 82			DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base);
 83			return PTR_ERR(dss->p0.base);
 84		}
 85	}
 86
 87	io->phy = devm_phy_get(&pdev->dev, "dp");
 88	if (IS_ERR(io->phy))
 89		return PTR_ERR(io->phy);
 90
 91	return 0;
 92}
 93
 94static u32 dp_parser_link_frequencies(struct device_node *of_node)
 95{
 96	struct device_node *endpoint;
 97	u64 frequency = 0;
 98	int cnt;
 99
100	endpoint = of_graph_get_endpoint_by_regs(of_node, 1, 0); /* port@1 */
101	if (!endpoint)
102		return 0;
103
104	cnt = of_property_count_u64_elems(endpoint, "link-frequencies");
105
106	if (cnt > 0)
107		of_property_read_u64_index(endpoint, "link-frequencies",
108						cnt - 1, &frequency);
109	of_node_put(endpoint);
110
111	do_div(frequency,
112		10 * /* from symbol rate to link rate */
113		1000); /* kbytes */
114
115	return frequency;
116}
117
118static int dp_parser_misc(struct dp_parser *parser)
119{
120	struct device_node *of_node = parser->pdev->dev.of_node;
121	int cnt;
122
123	/*
124	 * data-lanes is the property of dp_out endpoint
125	 */
126	cnt = drm_of_get_data_lanes_count_ep(of_node, 1, 0, 1, DP_MAX_NUM_DP_LANES);
127	if (cnt < 0) {
128		/* legacy code, data-lanes is the property of mdss_dp node */
129		cnt = drm_of_get_data_lanes_count(of_node, 1, DP_MAX_NUM_DP_LANES);
130	}
131
132	if (cnt > 0)
133		parser->max_dp_lanes = cnt;
134	else
135		parser->max_dp_lanes = DP_MAX_NUM_DP_LANES; /* 4 lanes */
136
137	parser->max_dp_link_rate = dp_parser_link_frequencies(of_node);
138	if (!parser->max_dp_link_rate)
139		parser->max_dp_link_rate = DP_LINK_RATE_HBR2;
140
141	return 0;
142}
143
144static inline bool dp_parser_check_prefix(const char *clk_prefix,
145						const char *clk_name)
146{
147	return !strncmp(clk_prefix, clk_name, strlen(clk_prefix));
148}
149
150static int dp_parser_init_clk_data(struct dp_parser *parser)
151{
152	int num_clk, i, rc;
153	int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
154	const char *clk_name;
155	struct device *dev = &parser->pdev->dev;
156	struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
157	struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
158	struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
159
160	num_clk = of_property_count_strings(dev->of_node, "clock-names");
161	if (num_clk <= 0) {
162		DRM_ERROR("no clocks are defined\n");
163		return -EINVAL;
164	}
165
166	for (i = 0; i < num_clk; i++) {
167		rc = of_property_read_string_index(dev->of_node,
168				"clock-names", i, &clk_name);
169		if (rc < 0)
170			return rc;
171
172		if (dp_parser_check_prefix("core", clk_name))
173			core_clk_count++;
174
175		if (dp_parser_check_prefix("ctrl", clk_name))
176			ctrl_clk_count++;
177
178		if (dp_parser_check_prefix("stream", clk_name))
179			stream_clk_count++;
180	}
181
182	/* Initialize the CORE power module */
183	if (core_clk_count == 0) {
184		DRM_ERROR("no core clocks are defined\n");
185		return -EINVAL;
186	}
187
188	core_power->num_clk = core_clk_count;
189	core_power->clocks = devm_kcalloc(dev,
190			core_power->num_clk, sizeof(struct clk_bulk_data),
191			GFP_KERNEL);
192	if (!core_power->clocks)
193		return -ENOMEM;
194
195	/* Initialize the CTRL power module */
196	if (ctrl_clk_count == 0) {
197		DRM_ERROR("no ctrl clocks are defined\n");
198		return -EINVAL;
199	}
200
201	ctrl_power->num_clk = ctrl_clk_count;
202	ctrl_power->clocks = devm_kcalloc(dev,
203			ctrl_power->num_clk, sizeof(struct clk_bulk_data),
204			GFP_KERNEL);
205	if (!ctrl_power->clocks) {
206		ctrl_power->num_clk = 0;
207		return -ENOMEM;
208	}
209
210	/* Initialize the STREAM power module */
211	if (stream_clk_count == 0) {
212		DRM_ERROR("no stream (pixel) clocks are defined\n");
213		return -EINVAL;
214	}
215
216	stream_power->num_clk = stream_clk_count;
217	stream_power->clocks = devm_kcalloc(dev,
218			stream_power->num_clk, sizeof(struct clk_bulk_data),
219			GFP_KERNEL);
220	if (!stream_power->clocks) {
221		stream_power->num_clk = 0;
222		return -ENOMEM;
223	}
224
225	return 0;
226}
227
228static int dp_parser_clock(struct dp_parser *parser)
229{
230	int rc = 0, i = 0;
231	int num_clk = 0;
232	int core_clk_index = 0, ctrl_clk_index = 0, stream_clk_index = 0;
233	int core_clk_count = 0, ctrl_clk_count = 0, stream_clk_count = 0;
234	const char *clk_name;
235	struct device *dev = &parser->pdev->dev;
236	struct dss_module_power *core_power = &parser->mp[DP_CORE_PM];
237	struct dss_module_power *ctrl_power = &parser->mp[DP_CTRL_PM];
238	struct dss_module_power *stream_power = &parser->mp[DP_STREAM_PM];
239
240	rc =  dp_parser_init_clk_data(parser);
241	if (rc) {
242		DRM_ERROR("failed to initialize power data %d\n", rc);
243		return -EINVAL;
244	}
245
246	core_clk_count = core_power->num_clk;
247	ctrl_clk_count = ctrl_power->num_clk;
248	stream_clk_count = stream_power->num_clk;
249
250	num_clk = core_clk_count + ctrl_clk_count + stream_clk_count;
251
252	for (i = 0; i < num_clk; i++) {
253		rc = of_property_read_string_index(dev->of_node, "clock-names",
254				i, &clk_name);
255		if (rc) {
256			DRM_ERROR("error reading clock-names %d\n", rc);
257			return rc;
258		}
259		if (dp_parser_check_prefix("core", clk_name) &&
260				core_clk_index < core_clk_count) {
261			core_power->clocks[core_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
262			core_clk_index++;
263		} else if (dp_parser_check_prefix("stream", clk_name) &&
264				stream_clk_index < stream_clk_count) {
265			stream_power->clocks[stream_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
266			stream_clk_index++;
267		} else if (dp_parser_check_prefix("ctrl", clk_name) &&
268			   ctrl_clk_index < ctrl_clk_count) {
269			ctrl_power->clocks[ctrl_clk_index].id = devm_kstrdup(dev, clk_name, GFP_KERNEL);
270			ctrl_clk_index++;
271		}
272	}
273
274	return 0;
275}
276
277int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser)
278{
279	struct platform_device *pdev = parser->pdev;
280	struct drm_bridge *bridge;
281
282	bridge = devm_drm_of_get_bridge(dev, pdev->dev.of_node, 1, 0);
283	if (IS_ERR(bridge))
284		return PTR_ERR(bridge);
285
286	parser->next_bridge = bridge;
287
288	return 0;
289}
290
291static int dp_parser_parse(struct dp_parser *parser)
292{
293	int rc = 0;
294
295	if (!parser) {
296		DRM_ERROR("invalid input\n");
297		return -EINVAL;
298	}
299
300	rc = dp_parser_ctrl_res(parser);
301	if (rc)
302		return rc;
303
304	rc = dp_parser_misc(parser);
305	if (rc)
306		return rc;
307
308	rc = dp_parser_clock(parser);
309	if (rc)
310		return rc;
311
312	return 0;
313}
314
315struct dp_parser *dp_parser_get(struct platform_device *pdev)
316{
317	struct dp_parser *parser;
318
319	parser = devm_kzalloc(&pdev->dev, sizeof(*parser), GFP_KERNEL);
320	if (!parser)
321		return ERR_PTR(-ENOMEM);
322
323	parser->parse = dp_parser_parse;
324	parser->pdev = pdev;
325
326	return parser;
327}