File Index
Files and directories
Sign in
FILE

msm_mdss.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/msm/msm_mdss.c C
  1/*
  2 * SPDX-License-Identifier: GPL-2.0
  3 * Copyright (c) 2018, The Linux Foundation
  4 */
  5
  6#include <linux/bitfield.h>
  7#include <linux/clk.h>
  8#include <linux/delay.h>
  9#include <linux/interconnect.h>
 10#include <linux/irq.h>
 11#include <linux/irqchip.h>
 12#include <linux/irqdesc.h>
 13#include <linux/irqchip/chained_irq.h>
 14#include <linux/of_platform.h>
 15#include <linux/platform_device.h>
 16#include <linux/pm_runtime.h>
 17#include <linux/reset.h>
 18
 19#include <linux/soc/qcom/ubwc.h>
 20
 21#include "msm_kms.h"
 22
 23#include <generated/mdss.xml.h>
 24
 25#define MIN_IB_BW	400000000UL /* Min ib vote 400MB */
 26
 27struct msm_mdss_data {
 28	u32 reg_bus_bw;
 29};
 30
 31struct msm_mdss {
 32	struct device *dev;
 33
 34	void __iomem *mmio;
 35	struct clk_bulk_data *clocks;
 36	size_t num_clocks;
 37	bool is_mdp5;
 38	struct {
 39		unsigned long enabled_mask;
 40		struct irq_domain *domain;
 41	} irq_controller;
 42	const struct qcom_ubwc_cfg_data *mdss_data;
 43	u32 reg_bus_bw;
 44	struct icc_path *mdp_path[2];
 45	u32 num_mdp_paths;
 46	struct icc_path *reg_bus_path;
 47};
 48
 49static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
 50					    struct msm_mdss *msm_mdss)
 51{
 52	struct icc_path *path0;
 53	struct icc_path *path1;
 54	struct icc_path *reg_bus_path;
 55
 56	path0 = devm_of_icc_get(dev, "mdp0-mem");
 57	if (IS_ERR_OR_NULL(path0))
 58		return PTR_ERR_OR_ZERO(path0);
 59
 60	msm_mdss->mdp_path[0] = path0;
 61	msm_mdss->num_mdp_paths = 1;
 62
 63	path1 = devm_of_icc_get(dev, "mdp1-mem");
 64	if (!IS_ERR_OR_NULL(path1)) {
 65		msm_mdss->mdp_path[1] = path1;
 66		msm_mdss->num_mdp_paths++;
 67	}
 68
 69	reg_bus_path = of_icc_get(dev, "cpu-cfg");
 70	if (!IS_ERR_OR_NULL(reg_bus_path))
 71		msm_mdss->reg_bus_path = reg_bus_path;
 72
 73	return 0;
 74}
 75
 76static void msm_mdss_irq(struct irq_desc *desc)
 77{
 78	struct msm_mdss *msm_mdss = irq_desc_get_handler_data(desc);
 79	struct irq_chip *chip = irq_desc_get_chip(desc);
 80	u32 interrupts;
 81
 82	chained_irq_enter(chip, desc);
 83
 84	interrupts = readl_relaxed(msm_mdss->mmio + REG_MDSS_HW_INTR_STATUS);
 85
 86	while (interrupts) {
 87		irq_hw_number_t hwirq = fls(interrupts) - 1;
 88		int rc;
 89
 90		rc = generic_handle_domain_irq(msm_mdss->irq_controller.domain,
 91					       hwirq);
 92		if (rc < 0) {
 93			dev_err(msm_mdss->dev, "handle irq fail: irq=%lu rc=%d\n",
 94				  hwirq, rc);
 95			break;
 96		}
 97
 98		interrupts &= ~(1 << hwirq);
 99	}
100
101	chained_irq_exit(chip, desc);
102}
103
104static void msm_mdss_irq_mask(struct irq_data *irqd)
105{
106	struct msm_mdss *msm_mdss = irq_data_get_irq_chip_data(irqd);
107
108	/* memory barrier */
109	smp_mb__before_atomic();
110	clear_bit(irqd->hwirq, &msm_mdss->irq_controller.enabled_mask);
111	/* memory barrier */
112	smp_mb__after_atomic();
113}
114
115static void msm_mdss_irq_unmask(struct irq_data *irqd)
116{
117	struct msm_mdss *msm_mdss = irq_data_get_irq_chip_data(irqd);
118
119	/* memory barrier */
120	smp_mb__before_atomic();
121	set_bit(irqd->hwirq, &msm_mdss->irq_controller.enabled_mask);
122	/* memory barrier */
123	smp_mb__after_atomic();
124}
125
126static struct irq_chip msm_mdss_irq_chip = {
127	.name = "msm_mdss",
128	.irq_mask = msm_mdss_irq_mask,
129	.irq_unmask = msm_mdss_irq_unmask,
130};
131
132static struct lock_class_key msm_mdss_lock_key, msm_mdss_request_key;
133
134static int msm_mdss_irqdomain_map(struct irq_domain *domain,
135		unsigned int irq, irq_hw_number_t hwirq)
136{
137	struct msm_mdss *msm_mdss = domain->host_data;
138
139	irq_set_lockdep_class(irq, &msm_mdss_lock_key, &msm_mdss_request_key);
140	irq_set_chip_and_handler(irq, &msm_mdss_irq_chip, handle_level_irq);
141
142	return irq_set_chip_data(irq, msm_mdss);
143}
144
145static const struct irq_domain_ops msm_mdss_irqdomain_ops = {
146	.map = msm_mdss_irqdomain_map,
147	.xlate = irq_domain_xlate_onecell,
148};
149
150static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
151{
152	struct device *dev;
153	struct irq_domain *domain;
154
155	dev = msm_mdss->dev;
156
157	domain = irq_domain_create_linear(dev_fwnode(dev), 32, &msm_mdss_irqdomain_ops, msm_mdss);
158	if (!domain) {
159		dev_err(dev, "failed to add irq_domain\n");
160		return -EINVAL;
161	}
162
163	msm_mdss->irq_controller.enabled_mask = 0;
164	msm_mdss->irq_controller.domain = domain;
165
166	return 0;
167}
168
169static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
170{
171	const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
172	u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
173		    MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
174
175	if (data->ubwc_bank_spread)
176		value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
177
178	if (data->ubwc_enc_version == UBWC_1_0)
179		value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1);
180
181	writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
182}
183
184static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
185{
186	const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
187	u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle & 0x1) |
188		    MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
189
190	if (data->macrotile_mode)
191		value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
192
193	if (data->ubwc_enc_version == UBWC_3_0)
194		value |= MDSS_UBWC_STATIC_UBWC_AMSBC;
195
196	if (data->ubwc_enc_version == UBWC_1_0)
197		value |= MDSS_UBWC_STATIC_UBWC_MIN_ACC_LEN(1);
198
199	writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
200}
201
202static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
203{
204	const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
205	u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
206		    MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
207
208	if (data->ubwc_bank_spread)
209		value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
210
211	if (data->macrotile_mode)
212		value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
213
214	writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
215
216	if (data->ubwc_enc_version == UBWC_3_0) {
217		writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
218		writel_relaxed(0, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
219	} else {
220		if (data->ubwc_dec_version == UBWC_4_3)
221			writel_relaxed(3, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
222		else
223			writel_relaxed(2, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
224		writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
225	}
226}
227
228static void msm_mdss_setup_ubwc_dec_50(struct msm_mdss *msm_mdss)
229{
230	const struct qcom_ubwc_cfg_data *data = msm_mdss->mdss_data;
231	u32 value = MDSS_UBWC_STATIC_UBWC_SWIZZLE(data->ubwc_swizzle) |
232		    MDSS_UBWC_STATIC_HIGHEST_BANK_BIT(data->highest_bank_bit - 13);
233
234	if (data->ubwc_bank_spread)
235		value |= MDSS_UBWC_STATIC_UBWC_BANK_SPREAD;
236
237	if (data->macrotile_mode)
238		value |= MDSS_UBWC_STATIC_MACROTILE_MODE;
239
240	writel_relaxed(value, msm_mdss->mmio + REG_MDSS_UBWC_STATIC);
241
242	writel_relaxed(4, msm_mdss->mmio + REG_MDSS_UBWC_CTRL_2);
243	writel_relaxed(1, msm_mdss->mmio + REG_MDSS_UBWC_PREDICTION_MODE);
244}
245
246static int msm_mdss_enable(struct msm_mdss *msm_mdss)
247{
248	int ret, i;
249
250	/*
251	 * Several components have AXI clocks that can only be turned on if
252	 * the interconnect is enabled (non-zero bandwidth). Let's make sure
253	 * that the interconnects are at least at a minimum amount.
254	 */
255	for (i = 0; i < msm_mdss->num_mdp_paths; i++)
256		icc_set_bw(msm_mdss->mdp_path[i], 0, Bps_to_icc(MIN_IB_BW));
257
258	icc_set_bw(msm_mdss->reg_bus_path, 0,
259		   msm_mdss->reg_bus_bw);
260
261	ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks);
262	if (ret) {
263		dev_err(msm_mdss->dev, "clock enable failed, ret:%d\n", ret);
264		return ret;
265	}
266
267	/*
268	 * Register access requires MDSS_MDP_CLK, which is not enabled by the
269	 * mdss on mdp5 hardware. Skip it for now.
270	 */
271	if (msm_mdss->is_mdp5 || !msm_mdss->mdss_data)
272		return 0;
273
274	/*
275	 * ubwc config is part of the "mdss" region which is not accessible
276	 * from the rest of the driver. hardcode known configurations here
277	 *
278	 * Decoder version can be read from the UBWC_DEC_HW_VERSION reg,
279	 * UBWC_n and the rest of params comes from hw data.
280	 */
281	switch (msm_mdss->mdss_data->ubwc_dec_version) {
282	case 0: /* no UBWC */
283	case UBWC_1_0:
284		/* do nothing */
285		break;
286	case UBWC_2_0:
287		msm_mdss_setup_ubwc_dec_20(msm_mdss);
288		break;
289	case UBWC_3_0:
290		msm_mdss_setup_ubwc_dec_30(msm_mdss);
291		break;
292	case UBWC_4_0:
293	case UBWC_4_3:
294		msm_mdss_setup_ubwc_dec_40(msm_mdss);
295		break;
296	case UBWC_5_0:
297		msm_mdss_setup_ubwc_dec_50(msm_mdss);
298		break;
299	default:
300		dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n",
301			msm_mdss->mdss_data->ubwc_dec_version);
302		dev_err(msm_mdss->dev, "HW_REV: 0x%x\n",
303			readl_relaxed(msm_mdss->mmio + REG_MDSS_HW_VERSION));
304		dev_err(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n",
305			readl_relaxed(msm_mdss->mmio + REG_MDSS_UBWC_DEC_HW_VERSION));
306		break;
307	}
308
309	return ret;
310}
311
312static int msm_mdss_disable(struct msm_mdss *msm_mdss)
313{
314	int i;
315
316	clk_bulk_disable_unprepare(msm_mdss->num_clocks, msm_mdss->clocks);
317
318	for (i = 0; i < msm_mdss->num_mdp_paths; i++)
319		icc_set_bw(msm_mdss->mdp_path[i], 0, 0);
320
321	if (msm_mdss->reg_bus_path)
322		icc_set_bw(msm_mdss->reg_bus_path, 0, 0);
323
324	return 0;
325}
326
327static void msm_mdss_destroy(struct msm_mdss *msm_mdss)
328{
329	struct platform_device *pdev = to_platform_device(msm_mdss->dev);
330	int irq;
331
332	pm_runtime_suspend(msm_mdss->dev);
333	pm_runtime_disable(msm_mdss->dev);
334	irq_domain_remove(msm_mdss->irq_controller.domain);
335	msm_mdss->irq_controller.domain = NULL;
336	irq = platform_get_irq(pdev, 0);
337	irq_set_chained_handler_and_data(irq, NULL, NULL);
338}
339
340static int msm_mdss_reset(struct device *dev)
341{
342	struct reset_control *reset;
343
344	reset = reset_control_get_optional_exclusive(dev, NULL);
345	if (!reset) {
346		/* Optional reset not specified */
347		return 0;
348	} else if (IS_ERR(reset)) {
349		return dev_err_probe(dev, PTR_ERR(reset),
350				     "failed to acquire mdss reset\n");
351	}
352
353	reset_control_assert(reset);
354	/*
355	 * Tests indicate that reset has to be held for some period of time,
356	 * make it one frame in a typical system
357	 */
358	msleep(20);
359	reset_control_deassert(reset);
360
361	reset_control_put(reset);
362
363	return 0;
364}
365
366/*
367 * MDP5 MDSS uses at most three specified clocks.
368 */
369#define MDP5_MDSS_NUM_CLOCKS 3
370static int mdp5_mdss_parse_clock(struct platform_device *pdev, struct clk_bulk_data **clocks)
371{
372	struct clk_bulk_data *bulk;
373	int num_clocks = 0;
374	int ret;
375
376	if (!pdev)
377		return -EINVAL;
378
379	bulk = devm_kcalloc(&pdev->dev, MDP5_MDSS_NUM_CLOCKS, sizeof(struct clk_bulk_data), GFP_KERNEL);
380	if (!bulk)
381		return -ENOMEM;
382
383	bulk[num_clocks++].id = "iface";
384	bulk[num_clocks++].id = "bus";
385	bulk[num_clocks++].id = "vsync";
386
387	ret = devm_clk_bulk_get_optional(&pdev->dev, num_clocks, bulk);
388	if (ret)
389		return ret;
390
391	*clocks = bulk;
392
393	return num_clocks;
394}
395
396static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5)
397{
398	const struct msm_mdss_data *mdss_data;
399	struct msm_mdss *msm_mdss;
400	int ret;
401	int irq;
402
403	ret = msm_mdss_reset(&pdev->dev);
404	if (ret)
405		return ERR_PTR(ret);
406
407	msm_mdss = devm_kzalloc(&pdev->dev, sizeof(*msm_mdss), GFP_KERNEL);
408	if (!msm_mdss)
409		return ERR_PTR(-ENOMEM);
410
411	msm_mdss->mdss_data = qcom_ubwc_config_get_data();
412	if (IS_ERR(msm_mdss->mdss_data))
413		return ERR_CAST(msm_mdss->mdss_data);
414
415	mdss_data = of_device_get_match_data(&pdev->dev);
416	if (!mdss_data)
417		return ERR_PTR(-EINVAL);
418
419	msm_mdss->reg_bus_bw = mdss_data->reg_bus_bw;
420
421	msm_mdss->mmio = devm_platform_ioremap_resource_byname(pdev, is_mdp5 ? "mdss_phys" : "mdss");
422	if (IS_ERR(msm_mdss->mmio))
423		return ERR_CAST(msm_mdss->mmio);
424
425	dev_dbg(&pdev->dev, "mapped mdss address space @%p\n", msm_mdss->mmio);
426
427	ret = msm_mdss_parse_data_bus_icc_path(&pdev->dev, msm_mdss);
428	if (ret)
429		return ERR_PTR(ret);
430
431	if (is_mdp5)
432		ret = mdp5_mdss_parse_clock(pdev, &msm_mdss->clocks);
433	else
434		ret = devm_clk_bulk_get_all(&pdev->dev, &msm_mdss->clocks);
435	if (ret < 0) {
436		dev_err(&pdev->dev, "failed to parse clocks, ret=%d\n", ret);
437		return ERR_PTR(ret);
438	}
439	msm_mdss->num_clocks = ret;
440	msm_mdss->is_mdp5 = is_mdp5;
441
442	msm_mdss->dev = &pdev->dev;
443
444	irq = platform_get_irq(pdev, 0);
445	if (irq < 0)
446		return ERR_PTR(irq);
447
448	ret = _msm_mdss_irq_domain_add(msm_mdss);
449	if (ret)
450		return ERR_PTR(ret);
451
452	irq_set_chained_handler_and_data(irq, msm_mdss_irq,
453					 msm_mdss);
454
455	pm_runtime_enable(&pdev->dev);
456
457	return msm_mdss;
458}
459
460static int __maybe_unused mdss_runtime_suspend(struct device *dev)
461{
462	struct msm_mdss *mdss = dev_get_drvdata(dev);
463
464	DBG("");
465
466	return msm_mdss_disable(mdss);
467}
468
469static int __maybe_unused mdss_runtime_resume(struct device *dev)
470{
471	struct msm_mdss *mdss = dev_get_drvdata(dev);
472
473	DBG("");
474
475	return msm_mdss_enable(mdss);
476}
477
478static int __maybe_unused mdss_pm_suspend(struct device *dev)
479{
480
481	if (pm_runtime_suspended(dev))
482		return 0;
483
484	return mdss_runtime_suspend(dev);
485}
486
487static int __maybe_unused mdss_pm_resume(struct device *dev)
488{
489	if (pm_runtime_suspended(dev))
490		return 0;
491
492	return mdss_runtime_resume(dev);
493}
494
495static const struct dev_pm_ops mdss_pm_ops = {
496	SET_SYSTEM_SLEEP_PM_OPS(mdss_pm_suspend, mdss_pm_resume)
497	SET_RUNTIME_PM_OPS(mdss_runtime_suspend, mdss_runtime_resume, NULL)
498};
499
500static int mdss_probe(struct platform_device *pdev)
501{
502	struct msm_mdss *mdss;
503	bool is_mdp5 = of_device_is_compatible(pdev->dev.of_node, "qcom,mdss");
504	struct device *dev = &pdev->dev;
505	int ret;
506
507	mdss = msm_mdss_init(pdev, is_mdp5);
508	if (IS_ERR(mdss))
509		return PTR_ERR(mdss);
510
511	platform_set_drvdata(pdev, mdss);
512
513	/*
514	 * MDP5/DPU based devices don't have a flat hierarchy. There is a top
515	 * level parent: MDSS, and children: MDP5/DPU, DSI, HDMI, eDP etc.
516	 * Populate the children devices, find the MDP5/DPU node, and then add
517	 * the interfaces to our components list.
518	 */
519	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
520	if (ret) {
521		DRM_DEV_ERROR(dev, "failed to populate children devices\n");
522		msm_mdss_destroy(mdss);
523		return ret;
524	}
525
526	return 0;
527}
528
529static void mdss_remove(struct platform_device *pdev)
530{
531	struct msm_mdss *mdss = platform_get_drvdata(pdev);
532
533	of_platform_depopulate(&pdev->dev);
534
535	msm_mdss_destroy(mdss);
536}
537
538static const struct msm_mdss_data data_57k = {
539	.reg_bus_bw = 57000,
540};
541
542static const struct msm_mdss_data data_74k = {
543	.reg_bus_bw = 74000,
544};
545
546static const struct msm_mdss_data data_76k8 = {
547	.reg_bus_bw = 76800,
548};
549
550static const struct msm_mdss_data data_153k6 = {
551	.reg_bus_bw = 153600,
552};
553
554static const struct of_device_id mdss_dt_match[] = {
555	{ .compatible = "qcom,mdss", .data = &data_153k6 },
556	{ .compatible = "qcom,glymur-mdss", .data = &data_57k },
557	{ .compatible = "qcom,msm8998-mdss", .data = &data_76k8 },
558	{ .compatible = "qcom,qcm2290-mdss", .data = &data_76k8 },
559	{ .compatible = "qcom,qcs8300-mdss", .data = &data_74k },
560	{ .compatible = "qcom,sa8775p-mdss", .data = &data_74k },
561	{ .compatible = "qcom,sar2130p-mdss", .data = &data_74k },
562	{ .compatible = "qcom,sdm670-mdss", .data = &data_76k8 },
563	{ .compatible = "qcom,sdm845-mdss", .data = &data_76k8 },
564	{ .compatible = "qcom,sc7180-mdss", .data = &data_76k8 },
565	{ .compatible = "qcom,sc7280-mdss", .data = &data_74k },
566	{ .compatible = "qcom,sc8180x-mdss", .data = &data_76k8 },
567	{ .compatible = "qcom,sc8280xp-mdss", .data = &data_76k8 },
568	{ .compatible = "qcom,sm6115-mdss", .data = &data_76k8 },
569	{ .compatible = "qcom,sm6125-mdss", .data = &data_76k8 },
570	{ .compatible = "qcom,sm6150-mdss", .data = &data_76k8 },
571	{ .compatible = "qcom,sm6350-mdss", .data = &data_76k8 },
572	{ .compatible = "qcom,sm6375-mdss", .data = &data_76k8 },
573	{ .compatible = "qcom,sm7150-mdss", .data = &data_76k8 },
574	{ .compatible = "qcom,sm8150-mdss", .data = &data_76k8 },
575	{ .compatible = "qcom,sm8250-mdss", .data = &data_76k8 },
576	{ .compatible = "qcom,sm8350-mdss", .data = &data_74k },
577	{ .compatible = "qcom,sm8450-mdss", .data = &data_74k },
578	{ .compatible = "qcom,sm8550-mdss", .data = &data_57k },
579	{ .compatible = "qcom,sm8650-mdss", .data = &data_57k },
580	{ .compatible = "qcom,sm8750-mdss", .data = &data_57k },
581	/* TODO: x1e8: Add reg_bus_bw with real value */
582	{ .compatible = "qcom,x1e80100-mdss", .data = &data_153k6 },
583	{}
584};
585MODULE_DEVICE_TABLE(of, mdss_dt_match);
586
587static struct platform_driver mdss_platform_driver = {
588	.probe      = mdss_probe,
589	.remove     = mdss_remove,
590	.driver     = {
591		.name   = "msm-mdss",
592		.of_match_table = mdss_dt_match,
593		.pm     = &mdss_pm_ops,
594	},
595};
596
597void __init msm_mdss_register(void)
598{
599	platform_driver_register(&mdss_platform_driver);
600}
601
602void __exit msm_mdss_unregister(void)
603{
604	platform_driver_unregister(&mdss_platform_driver);
605}
~/ Read-only file preview.