187729e2aSDmitry Baryshkov /*
287729e2aSDmitry Baryshkov * SPDX-License-Identifier: GPL-2.0
387729e2aSDmitry Baryshkov * Copyright (c) 2018, The Linux Foundation
487729e2aSDmitry Baryshkov */
587729e2aSDmitry Baryshkov
6e1072257SDmitry Baryshkov #include <linux/clk.h>
73e9c146fSBjorn Andersson #include <linux/delay.h>
8b9364eedSDouglas Anderson #include <linux/interconnect.h>
987729e2aSDmitry Baryshkov #include <linux/irq.h>
1087729e2aSDmitry Baryshkov #include <linux/irqchip.h>
1187729e2aSDmitry Baryshkov #include <linux/irqdesc.h>
1287729e2aSDmitry Baryshkov #include <linux/irqchip/chained_irq.h>
13722d4f06SRob Herring #include <linux/of_platform.h>
14722d4f06SRob Herring #include <linux/platform_device.h>
15e1072257SDmitry Baryshkov #include <linux/pm_runtime.h>
163e9c146fSBjorn Andersson #include <linux/reset.h>
1787729e2aSDmitry Baryshkov
1871e00fc0SDmitry Baryshkov #include "msm_mdss.h"
19ecb23f2eSDmitry Baryshkov #include "msm_kms.h"
20ecb23f2eSDmitry Baryshkov
2187729e2aSDmitry Baryshkov #define HW_REV 0x0
2287729e2aSDmitry Baryshkov #define HW_INTR_STATUS 0x0010
2387729e2aSDmitry Baryshkov
2492bab914SDmitry Baryshkov #define UBWC_DEC_HW_VERSION 0x58
2587729e2aSDmitry Baryshkov #define UBWC_STATIC 0x144
2687729e2aSDmitry Baryshkov #define UBWC_CTRL_2 0x150
2787729e2aSDmitry Baryshkov #define UBWC_PREDICTION_MODE 0x154
2887729e2aSDmitry Baryshkov
29b9364eedSDouglas Anderson #define MIN_IB_BW 400000000UL /* Min ib vote 400MB */
30b9364eedSDouglas Anderson
31aba75693SDmitry Baryshkov #define DEFAULT_REG_BW 153600 /* Used in mdss fbdev driver */
32aba75693SDmitry Baryshkov
33e1072257SDmitry Baryshkov struct msm_mdss {
34e1072257SDmitry Baryshkov struct device *dev;
35e1072257SDmitry Baryshkov
3687729e2aSDmitry Baryshkov void __iomem *mmio;
3787729e2aSDmitry Baryshkov struct clk_bulk_data *clocks;
3887729e2aSDmitry Baryshkov size_t num_clocks;
3987729e2aSDmitry Baryshkov bool is_mdp5;
4087729e2aSDmitry Baryshkov struct {
4187729e2aSDmitry Baryshkov unsigned long enabled_mask;
4287729e2aSDmitry Baryshkov struct irq_domain *domain;
4387729e2aSDmitry Baryshkov } irq_controller;
44d68db606SDmitry Baryshkov const struct msm_mdss_data *mdss_data;
45707601fcSKonrad Dybcio struct icc_path *mdp_path[2];
46707601fcSKonrad Dybcio u32 num_mdp_paths;
47aba75693SDmitry Baryshkov struct icc_path *reg_bus_path;
4887729e2aSDmitry Baryshkov };
4987729e2aSDmitry Baryshkov
msm_mdss_parse_data_bus_icc_path(struct device * dev,struct msm_mdss * msm_mdss)50b9364eedSDouglas Anderson static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
51b9364eedSDouglas Anderson struct msm_mdss *msm_mdss)
52b9364eedSDouglas Anderson {
5345dac135SMiaoqian Lin struct icc_path *path0;
5445dac135SMiaoqian Lin struct icc_path *path1;
55aba75693SDmitry Baryshkov struct icc_path *reg_bus_path;
56b9364eedSDouglas Anderson
579611899fSDmitry Baryshkov path0 = devm_of_icc_get(dev, "mdp0-mem");
58b9364eedSDouglas Anderson if (IS_ERR_OR_NULL(path0))
59b9364eedSDouglas Anderson return PTR_ERR_OR_ZERO(path0);
60b9364eedSDouglas Anderson
61707601fcSKonrad Dybcio msm_mdss->mdp_path[0] = path0;
62707601fcSKonrad Dybcio msm_mdss->num_mdp_paths = 1;
63b9364eedSDouglas Anderson
649611899fSDmitry Baryshkov path1 = devm_of_icc_get(dev, "mdp1-mem");
65b9364eedSDouglas Anderson if (!IS_ERR_OR_NULL(path1)) {
66707601fcSKonrad Dybcio msm_mdss->mdp_path[1] = path1;
67707601fcSKonrad Dybcio msm_mdss->num_mdp_paths++;
68b9364eedSDouglas Anderson }
69b9364eedSDouglas Anderson
70aba75693SDmitry Baryshkov reg_bus_path = of_icc_get(dev, "cpu-cfg");
71aba75693SDmitry Baryshkov if (!IS_ERR_OR_NULL(reg_bus_path))
72aba75693SDmitry Baryshkov msm_mdss->reg_bus_path = reg_bus_path;
73aba75693SDmitry Baryshkov
74b9364eedSDouglas Anderson return 0;
75b9364eedSDouglas Anderson }
76b9364eedSDouglas Anderson
msm_mdss_icc_request_bw(struct msm_mdss * msm_mdss,unsigned long bw)77b9364eedSDouglas Anderson static void msm_mdss_icc_request_bw(struct msm_mdss *msm_mdss, unsigned long bw)
78b9364eedSDouglas Anderson {
79b9364eedSDouglas Anderson int i;
80b9364eedSDouglas Anderson
81707601fcSKonrad Dybcio for (i = 0; i < msm_mdss->num_mdp_paths; i++)
82707601fcSKonrad Dybcio icc_set_bw(msm_mdss->mdp_path[i], 0, Bps_to_icc(bw));
83b9364eedSDouglas Anderson }
84b9364eedSDouglas Anderson
msm_mdss_irq(struct irq_desc * desc)8587729e2aSDmitry Baryshkov static void msm_mdss_irq(struct irq_desc *desc)
8687729e2aSDmitry Baryshkov {
87e1072257SDmitry Baryshkov struct msm_mdss *msm_mdss = irq_desc_get_handler_data(desc);
8887729e2aSDmitry Baryshkov struct irq_chip *chip = irq_desc_get_chip(desc);
8987729e2aSDmitry Baryshkov u32 interrupts;
9087729e2aSDmitry Baryshkov
9187729e2aSDmitry Baryshkov chained_irq_enter(chip, desc);
9287729e2aSDmitry Baryshkov
93e1072257SDmitry Baryshkov interrupts = readl_relaxed(msm_mdss->mmio + HW_INTR_STATUS);
9487729e2aSDmitry Baryshkov
9587729e2aSDmitry Baryshkov while (interrupts) {
9687729e2aSDmitry Baryshkov irq_hw_number_t hwirq = fls(interrupts) - 1;
9787729e2aSDmitry Baryshkov int rc;
9887729e2aSDmitry Baryshkov
99e1072257SDmitry Baryshkov rc = generic_handle_domain_irq(msm_mdss->irq_controller.domain,
10087729e2aSDmitry Baryshkov hwirq);
10187729e2aSDmitry Baryshkov if (rc < 0) {
102e1072257SDmitry Baryshkov dev_err(msm_mdss->dev, "handle irq fail: irq=%lu rc=%d\n",
10387729e2aSDmitry Baryshkov hwirq, rc);
10487729e2aSDmitry Baryshkov break;
10587729e2aSDmitry Baryshkov }
10687729e2aSDmitry Baryshkov
10787729e2aSDmitry Baryshkov interrupts &= ~(1 << hwirq);
10887729e2aSDmitry Baryshkov }
10987729e2aSDmitry Baryshkov
11087729e2aSDmitry Baryshkov chained_irq_exit(chip, desc);
11187729e2aSDmitry Baryshkov }
11287729e2aSDmitry Baryshkov
msm_mdss_irq_mask(struct irq_data * irqd)11387729e2aSDmitry Baryshkov static void msm_mdss_irq_mask(struct irq_data *irqd)
11487729e2aSDmitry Baryshkov {
115e1072257SDmitry Baryshkov struct msm_mdss *msm_mdss = irq_data_get_irq_chip_data(irqd);
11687729e2aSDmitry Baryshkov
11787729e2aSDmitry Baryshkov /* memory barrier */
11887729e2aSDmitry Baryshkov smp_mb__before_atomic();
119e1072257SDmitry Baryshkov clear_bit(irqd->hwirq, &msm_mdss->irq_controller.enabled_mask);
12087729e2aSDmitry Baryshkov /* memory barrier */
12187729e2aSDmitry Baryshkov smp_mb__after_atomic();
12287729e2aSDmitry Baryshkov }
12387729e2aSDmitry Baryshkov
msm_mdss_irq_unmask(struct irq_data * irqd)12487729e2aSDmitry Baryshkov static void msm_mdss_irq_unmask(struct irq_data *irqd)
12587729e2aSDmitry Baryshkov {
126e1072257SDmitry Baryshkov struct msm_mdss *msm_mdss = irq_data_get_irq_chip_data(irqd);
12787729e2aSDmitry Baryshkov
12887729e2aSDmitry Baryshkov /* memory barrier */
12987729e2aSDmitry Baryshkov smp_mb__before_atomic();
130e1072257SDmitry Baryshkov set_bit(irqd->hwirq, &msm_mdss->irq_controller.enabled_mask);
13187729e2aSDmitry Baryshkov /* memory barrier */
13287729e2aSDmitry Baryshkov smp_mb__after_atomic();
13387729e2aSDmitry Baryshkov }
13487729e2aSDmitry Baryshkov
13587729e2aSDmitry Baryshkov static struct irq_chip msm_mdss_irq_chip = {
136e1072257SDmitry Baryshkov .name = "msm_mdss",
13787729e2aSDmitry Baryshkov .irq_mask = msm_mdss_irq_mask,
13887729e2aSDmitry Baryshkov .irq_unmask = msm_mdss_irq_unmask,
13987729e2aSDmitry Baryshkov };
14087729e2aSDmitry Baryshkov
14187729e2aSDmitry Baryshkov static struct lock_class_key msm_mdss_lock_key, msm_mdss_request_key;
14287729e2aSDmitry Baryshkov
msm_mdss_irqdomain_map(struct irq_domain * domain,unsigned int irq,irq_hw_number_t hwirq)14387729e2aSDmitry Baryshkov static int msm_mdss_irqdomain_map(struct irq_domain *domain,
14487729e2aSDmitry Baryshkov unsigned int irq, irq_hw_number_t hwirq)
14587729e2aSDmitry Baryshkov {
146e1072257SDmitry Baryshkov struct msm_mdss *msm_mdss = domain->host_data;
14787729e2aSDmitry Baryshkov
14887729e2aSDmitry Baryshkov irq_set_lockdep_class(irq, &msm_mdss_lock_key, &msm_mdss_request_key);
14987729e2aSDmitry Baryshkov irq_set_chip_and_handler(irq, &msm_mdss_irq_chip, handle_level_irq);
15087729e2aSDmitry Baryshkov
151e1072257SDmitry Baryshkov return irq_set_chip_data(irq, msm_mdss);
15287729e2aSDmitry Baryshkov }
15387729e2aSDmitry Baryshkov
15487729e2aSDmitry Baryshkov static const struct irq_domain_ops msm_mdss_irqdomain_ops = {
15587729e2aSDmitry Baryshkov .map = msm_mdss_irqdomain_map,
15687729e2aSDmitry Baryshkov .xlate = irq_domain_xlate_onecell,
15787729e2aSDmitry Baryshkov };
15887729e2aSDmitry Baryshkov
_msm_mdss_irq_domain_add(struct msm_mdss * msm_mdss)159e1072257SDmitry Baryshkov static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
16087729e2aSDmitry Baryshkov {
16187729e2aSDmitry Baryshkov struct device *dev;
16287729e2aSDmitry Baryshkov struct irq_domain *domain;
16387729e2aSDmitry Baryshkov
164e1072257SDmitry Baryshkov dev = msm_mdss->dev;
16587729e2aSDmitry Baryshkov
16687729e2aSDmitry Baryshkov domain = irq_domain_add_linear(dev->of_node, 32,
167e1072257SDmitry Baryshkov &msm_mdss_irqdomain_ops, msm_mdss);
16887729e2aSDmitry Baryshkov if (!domain) {
169e1072257SDmitry Baryshkov dev_err(dev, "failed to add irq_domain\n");
17087729e2aSDmitry Baryshkov return -EINVAL;
17187729e2aSDmitry Baryshkov }
17287729e2aSDmitry Baryshkov
173e1072257SDmitry Baryshkov msm_mdss->irq_controller.enabled_mask = 0;
174e1072257SDmitry Baryshkov msm_mdss->irq_controller.domain = domain;
17587729e2aSDmitry Baryshkov
17687729e2aSDmitry Baryshkov return 0;
17787729e2aSDmitry Baryshkov }
17887729e2aSDmitry Baryshkov
msm_mdss_setup_ubwc_dec_20(struct msm_mdss * msm_mdss)179d68db606SDmitry Baryshkov static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
18092bab914SDmitry Baryshkov {
181d68db606SDmitry Baryshkov const struct msm_mdss_data *data = msm_mdss->mdss_data;
182d68db606SDmitry Baryshkov
183d68db606SDmitry Baryshkov writel_relaxed(data->ubwc_static, msm_mdss->mmio + UBWC_STATIC);
18492bab914SDmitry Baryshkov }
18592bab914SDmitry Baryshkov
msm_mdss_setup_ubwc_dec_30(struct msm_mdss * msm_mdss)186d68db606SDmitry Baryshkov static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss)
18792bab914SDmitry Baryshkov {
188d68db606SDmitry Baryshkov const struct msm_mdss_data *data = msm_mdss->mdss_data;
189d68db606SDmitry Baryshkov u32 value = (data->ubwc_swizzle & 0x1) |
190d68db606SDmitry Baryshkov (data->highest_bank_bit & 0x3) << 4 |
191d68db606SDmitry Baryshkov (data->macrotile_mode & 0x1) << 12;
19292bab914SDmitry Baryshkov
193cab5b406SDmitry Baryshkov if (data->ubwc_enc_version == UBWC_3_0)
19492bab914SDmitry Baryshkov value |= BIT(10);
19592bab914SDmitry Baryshkov
196cab5b406SDmitry Baryshkov if (data->ubwc_enc_version == UBWC_1_0)
19792bab914SDmitry Baryshkov value |= BIT(8);
19892bab914SDmitry Baryshkov
19992bab914SDmitry Baryshkov writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
20092bab914SDmitry Baryshkov }
20192bab914SDmitry Baryshkov
msm_mdss_setup_ubwc_dec_40(struct msm_mdss * msm_mdss)202d68db606SDmitry Baryshkov static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
20392bab914SDmitry Baryshkov {
204d68db606SDmitry Baryshkov const struct msm_mdss_data *data = msm_mdss->mdss_data;
205d68db606SDmitry Baryshkov u32 value = (data->ubwc_swizzle & 0x7) |
206d68db606SDmitry Baryshkov (data->ubwc_static & 0x1) << 3 |
207d68db606SDmitry Baryshkov (data->highest_bank_bit & 0x7) << 4 |
208d68db606SDmitry Baryshkov (data->macrotile_mode & 0x1) << 12;
20992bab914SDmitry Baryshkov
21092bab914SDmitry Baryshkov writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
21192bab914SDmitry Baryshkov
212cab5b406SDmitry Baryshkov if (data->ubwc_enc_version == UBWC_3_0) {
21392bab914SDmitry Baryshkov writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2);
21492bab914SDmitry Baryshkov writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE);
21592bab914SDmitry Baryshkov } else {
216a85c238cSDmitry Baryshkov if (data->ubwc_dec_version == UBWC_4_3)
217a85c238cSDmitry Baryshkov writel_relaxed(3, msm_mdss->mmio + UBWC_CTRL_2);
218a85c238cSDmitry Baryshkov else
21992bab914SDmitry Baryshkov writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
22092bab914SDmitry Baryshkov writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
22192bab914SDmitry Baryshkov }
22292bab914SDmitry Baryshkov }
22392bab914SDmitry Baryshkov
msm_mdss_get_mdss_data(struct device * dev)22471e00fc0SDmitry Baryshkov const struct msm_mdss_data *msm_mdss_get_mdss_data(struct device *dev)
22571e00fc0SDmitry Baryshkov {
22671e00fc0SDmitry Baryshkov struct msm_mdss *mdss;
22771e00fc0SDmitry Baryshkov
22871e00fc0SDmitry Baryshkov if (!dev)
22971e00fc0SDmitry Baryshkov return ERR_PTR(-EINVAL);
23071e00fc0SDmitry Baryshkov
23171e00fc0SDmitry Baryshkov mdss = dev_get_drvdata(dev);
23271e00fc0SDmitry Baryshkov
23371e00fc0SDmitry Baryshkov return mdss->mdss_data;
23471e00fc0SDmitry Baryshkov }
23571e00fc0SDmitry Baryshkov
msm_mdss_enable(struct msm_mdss * msm_mdss)236ecb23f2eSDmitry Baryshkov static int msm_mdss_enable(struct msm_mdss *msm_mdss)
23787729e2aSDmitry Baryshkov {
23887729e2aSDmitry Baryshkov int ret;
23987729e2aSDmitry Baryshkov
240b9364eedSDouglas Anderson /*
241b9364eedSDouglas Anderson * Several components have AXI clocks that can only be turned on if
242b9364eedSDouglas Anderson * the interconnect is enabled (non-zero bandwidth). Let's make sure
243b9364eedSDouglas Anderson * that the interconnects are at least at a minimum amount.
244b9364eedSDouglas Anderson */
245b9364eedSDouglas Anderson msm_mdss_icc_request_bw(msm_mdss, MIN_IB_BW);
246b9364eedSDouglas Anderson
247aba75693SDmitry Baryshkov if (msm_mdss->mdss_data && msm_mdss->mdss_data->reg_bus_bw)
248aba75693SDmitry Baryshkov icc_set_bw(msm_mdss->reg_bus_path, 0,
249aba75693SDmitry Baryshkov msm_mdss->mdss_data->reg_bus_bw);
250aba75693SDmitry Baryshkov else
251aba75693SDmitry Baryshkov icc_set_bw(msm_mdss->reg_bus_path, 0,
252aba75693SDmitry Baryshkov DEFAULT_REG_BW);
253aba75693SDmitry Baryshkov
254e1072257SDmitry Baryshkov ret = clk_bulk_prepare_enable(msm_mdss->num_clocks, msm_mdss->clocks);
25587729e2aSDmitry Baryshkov if (ret) {
256e1072257SDmitry Baryshkov dev_err(msm_mdss->dev, "clock enable failed, ret:%d\n", ret);
25787729e2aSDmitry Baryshkov return ret;
25887729e2aSDmitry Baryshkov }
25987729e2aSDmitry Baryshkov
26087729e2aSDmitry Baryshkov /*
261d68db606SDmitry Baryshkov * Register access requires MDSS_MDP_CLK, which is not enabled by the
262d68db606SDmitry Baryshkov * mdss on mdp5 hardware. Skip it for now.
26387729e2aSDmitry Baryshkov */
264d68db606SDmitry Baryshkov if (msm_mdss->is_mdp5 || !msm_mdss->mdss_data)
26587729e2aSDmitry Baryshkov return 0;
26687729e2aSDmitry Baryshkov
26787729e2aSDmitry Baryshkov /*
26887729e2aSDmitry Baryshkov * ubwc config is part of the "mdss" region which is not accessible
26987729e2aSDmitry Baryshkov * from the rest of the driver. hardcode known configurations here
27092bab914SDmitry Baryshkov *
27192bab914SDmitry Baryshkov * Decoder version can be read from the UBWC_DEC_HW_VERSION reg,
272d68db606SDmitry Baryshkov * UBWC_n and the rest of params comes from hw data.
27387729e2aSDmitry Baryshkov */
274d68db606SDmitry Baryshkov switch (msm_mdss->mdss_data->ubwc_dec_version) {
2756f410b24SDmitry Baryshkov case 0: /* no UBWC */
2766f410b24SDmitry Baryshkov case UBWC_1_0:
2776f410b24SDmitry Baryshkov /* do nothing */
2786f410b24SDmitry Baryshkov break;
279d68db606SDmitry Baryshkov case UBWC_2_0:
280d68db606SDmitry Baryshkov msm_mdss_setup_ubwc_dec_20(msm_mdss);
28187729e2aSDmitry Baryshkov break;
282d68db606SDmitry Baryshkov case UBWC_3_0:
283d68db606SDmitry Baryshkov msm_mdss_setup_ubwc_dec_30(msm_mdss);
28487729e2aSDmitry Baryshkov break;
285d68db606SDmitry Baryshkov case UBWC_4_0:
286a85c238cSDmitry Baryshkov case UBWC_4_3:
287d68db606SDmitry Baryshkov msm_mdss_setup_ubwc_dec_40(msm_mdss);
28887729e2aSDmitry Baryshkov break;
289d68db606SDmitry Baryshkov default:
2906ec59381SColin Ian King dev_err(msm_mdss->dev, "Unsupported UBWC decoder version %x\n",
291d68db606SDmitry Baryshkov msm_mdss->mdss_data->ubwc_dec_version);
292d68db606SDmitry Baryshkov dev_err(msm_mdss->dev, "HW_REV: 0x%x\n",
293d68db606SDmitry Baryshkov readl_relaxed(msm_mdss->mmio + HW_REV));
294d68db606SDmitry Baryshkov dev_err(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n",
295d68db606SDmitry Baryshkov readl_relaxed(msm_mdss->mmio + UBWC_DEC_HW_VERSION));
29680056d9aSDmitry Baryshkov break;
29787729e2aSDmitry Baryshkov }
29887729e2aSDmitry Baryshkov
29987729e2aSDmitry Baryshkov return ret;
30087729e2aSDmitry Baryshkov }
30187729e2aSDmitry Baryshkov
msm_mdss_disable(struct msm_mdss * msm_mdss)302ecb23f2eSDmitry Baryshkov static int msm_mdss_disable(struct msm_mdss *msm_mdss)
30387729e2aSDmitry Baryshkov {
304e1072257SDmitry Baryshkov clk_bulk_disable_unprepare(msm_mdss->num_clocks, msm_mdss->clocks);
305b9364eedSDouglas Anderson msm_mdss_icc_request_bw(msm_mdss, 0);
30687729e2aSDmitry Baryshkov
307aba75693SDmitry Baryshkov if (msm_mdss->reg_bus_path)
308aba75693SDmitry Baryshkov icc_set_bw(msm_mdss->reg_bus_path, 0, 0);
309aba75693SDmitry Baryshkov
31087729e2aSDmitry Baryshkov return 0;
31187729e2aSDmitry Baryshkov }
31287729e2aSDmitry Baryshkov
msm_mdss_destroy(struct msm_mdss * msm_mdss)313ecb23f2eSDmitry Baryshkov static void msm_mdss_destroy(struct msm_mdss *msm_mdss)
31487729e2aSDmitry Baryshkov {
315e1072257SDmitry Baryshkov struct platform_device *pdev = to_platform_device(msm_mdss->dev);
31687729e2aSDmitry Baryshkov int irq;
31787729e2aSDmitry Baryshkov
318e1072257SDmitry Baryshkov pm_runtime_suspend(msm_mdss->dev);
319e1072257SDmitry Baryshkov pm_runtime_disable(msm_mdss->dev);
320e1072257SDmitry Baryshkov irq_domain_remove(msm_mdss->irq_controller.domain);
321e1072257SDmitry Baryshkov msm_mdss->irq_controller.domain = NULL;
32287729e2aSDmitry Baryshkov irq = platform_get_irq(pdev, 0);
32387729e2aSDmitry Baryshkov irq_set_chained_handler_and_data(irq, NULL, NULL);
32487729e2aSDmitry Baryshkov }
32587729e2aSDmitry Baryshkov
msm_mdss_reset(struct device * dev)3263e9c146fSBjorn Andersson static int msm_mdss_reset(struct device *dev)
3273e9c146fSBjorn Andersson {
3283e9c146fSBjorn Andersson struct reset_control *reset;
3293e9c146fSBjorn Andersson
3303e9c146fSBjorn Andersson reset = reset_control_get_optional_exclusive(dev, NULL);
3313e9c146fSBjorn Andersson if (!reset) {
3323e9c146fSBjorn Andersson /* Optional reset not specified */
3333e9c146fSBjorn Andersson return 0;
3343e9c146fSBjorn Andersson } else if (IS_ERR(reset)) {
3353e9c146fSBjorn Andersson return dev_err_probe(dev, PTR_ERR(reset),
3363e9c146fSBjorn Andersson "failed to acquire mdss reset\n");
3373e9c146fSBjorn Andersson }
3383e9c146fSBjorn Andersson
3393e9c146fSBjorn Andersson reset_control_assert(reset);
3403e9c146fSBjorn Andersson /*
3413e9c146fSBjorn Andersson * Tests indicate that reset has to be held for some period of time,
3423e9c146fSBjorn Andersson * make it one frame in a typical system
3433e9c146fSBjorn Andersson */
3443e9c146fSBjorn Andersson msleep(20);
3453e9c146fSBjorn Andersson reset_control_deassert(reset);
3463e9c146fSBjorn Andersson
3473e9c146fSBjorn Andersson reset_control_put(reset);
3483e9c146fSBjorn Andersson
3493e9c146fSBjorn Andersson return 0;
3503e9c146fSBjorn Andersson }
3513e9c146fSBjorn Andersson
35287729e2aSDmitry Baryshkov /*
35387729e2aSDmitry Baryshkov * MDP5 MDSS uses at most three specified clocks.
35487729e2aSDmitry Baryshkov */
35587729e2aSDmitry Baryshkov #define MDP5_MDSS_NUM_CLOCKS 3
mdp5_mdss_parse_clock(struct platform_device * pdev,struct clk_bulk_data ** clocks)35687729e2aSDmitry Baryshkov static int mdp5_mdss_parse_clock(struct platform_device *pdev, struct clk_bulk_data **clocks)
35787729e2aSDmitry Baryshkov {
35887729e2aSDmitry Baryshkov struct clk_bulk_data *bulk;
35987729e2aSDmitry Baryshkov int num_clocks = 0;
36087729e2aSDmitry Baryshkov int ret;
36187729e2aSDmitry Baryshkov
36287729e2aSDmitry Baryshkov if (!pdev)
36387729e2aSDmitry Baryshkov return -EINVAL;
36487729e2aSDmitry Baryshkov
36587729e2aSDmitry Baryshkov bulk = devm_kcalloc(&pdev->dev, MDP5_MDSS_NUM_CLOCKS, sizeof(struct clk_bulk_data), GFP_KERNEL);
36687729e2aSDmitry Baryshkov if (!bulk)
36787729e2aSDmitry Baryshkov return -ENOMEM;
36887729e2aSDmitry Baryshkov
36987729e2aSDmitry Baryshkov bulk[num_clocks++].id = "iface";
37087729e2aSDmitry Baryshkov bulk[num_clocks++].id = "bus";
37187729e2aSDmitry Baryshkov bulk[num_clocks++].id = "vsync";
37287729e2aSDmitry Baryshkov
37387729e2aSDmitry Baryshkov ret = devm_clk_bulk_get_optional(&pdev->dev, num_clocks, bulk);
37487729e2aSDmitry Baryshkov if (ret)
37587729e2aSDmitry Baryshkov return ret;
37687729e2aSDmitry Baryshkov
37787729e2aSDmitry Baryshkov *clocks = bulk;
37887729e2aSDmitry Baryshkov
37987729e2aSDmitry Baryshkov return num_clocks;
38087729e2aSDmitry Baryshkov }
38187729e2aSDmitry Baryshkov
msm_mdss_init(struct platform_device * pdev,bool is_mdp5)382ecb23f2eSDmitry Baryshkov static struct msm_mdss *msm_mdss_init(struct platform_device *pdev, bool is_mdp5)
38387729e2aSDmitry Baryshkov {
384e1072257SDmitry Baryshkov struct msm_mdss *msm_mdss;
38587729e2aSDmitry Baryshkov int ret;
38687729e2aSDmitry Baryshkov int irq;
38787729e2aSDmitry Baryshkov
3883e9c146fSBjorn Andersson ret = msm_mdss_reset(&pdev->dev);
3893e9c146fSBjorn Andersson if (ret)
3903e9c146fSBjorn Andersson return ERR_PTR(ret);
3913e9c146fSBjorn Andersson
392e1072257SDmitry Baryshkov msm_mdss = devm_kzalloc(&pdev->dev, sizeof(*msm_mdss), GFP_KERNEL);
393e1072257SDmitry Baryshkov if (!msm_mdss)
394e1072257SDmitry Baryshkov return ERR_PTR(-ENOMEM);
39587729e2aSDmitry Baryshkov
396aba75693SDmitry Baryshkov msm_mdss->mdss_data = of_device_get_match_data(&pdev->dev);
397aba75693SDmitry Baryshkov
398e1072257SDmitry Baryshkov msm_mdss->mmio = devm_platform_ioremap_resource_byname(pdev, is_mdp5 ? "mdss_phys" : "mdss");
399e1072257SDmitry Baryshkov if (IS_ERR(msm_mdss->mmio))
400e1072257SDmitry Baryshkov return ERR_CAST(msm_mdss->mmio);
40187729e2aSDmitry Baryshkov
402e1072257SDmitry Baryshkov dev_dbg(&pdev->dev, "mapped mdss address space @%pK\n", msm_mdss->mmio);
40387729e2aSDmitry Baryshkov
404b9364eedSDouglas Anderson ret = msm_mdss_parse_data_bus_icc_path(&pdev->dev, msm_mdss);
405b9364eedSDouglas Anderson if (ret)
406b9364eedSDouglas Anderson return ERR_PTR(ret);
407b9364eedSDouglas Anderson
40887729e2aSDmitry Baryshkov if (is_mdp5)
409e1072257SDmitry Baryshkov ret = mdp5_mdss_parse_clock(pdev, &msm_mdss->clocks);
41087729e2aSDmitry Baryshkov else
411e1072257SDmitry Baryshkov ret = devm_clk_bulk_get_all(&pdev->dev, &msm_mdss->clocks);
41287729e2aSDmitry Baryshkov if (ret < 0) {
413e1072257SDmitry Baryshkov dev_err(&pdev->dev, "failed to parse clocks, ret=%d\n", ret);
414e1072257SDmitry Baryshkov return ERR_PTR(ret);
41587729e2aSDmitry Baryshkov }
416e1072257SDmitry Baryshkov msm_mdss->num_clocks = ret;
417e1072257SDmitry Baryshkov msm_mdss->is_mdp5 = is_mdp5;
41887729e2aSDmitry Baryshkov
419e1072257SDmitry Baryshkov msm_mdss->dev = &pdev->dev;
42087729e2aSDmitry Baryshkov
42187729e2aSDmitry Baryshkov irq = platform_get_irq(pdev, 0);
42287729e2aSDmitry Baryshkov if (irq < 0)
423e1072257SDmitry Baryshkov return ERR_PTR(irq);
42487729e2aSDmitry Baryshkov
425e1072257SDmitry Baryshkov ret = _msm_mdss_irq_domain_add(msm_mdss);
42687729e2aSDmitry Baryshkov if (ret)
427e1072257SDmitry Baryshkov return ERR_PTR(ret);
42887729e2aSDmitry Baryshkov
42987729e2aSDmitry Baryshkov irq_set_chained_handler_and_data(irq, msm_mdss_irq,
430e1072257SDmitry Baryshkov msm_mdss);
43187729e2aSDmitry Baryshkov
43287729e2aSDmitry Baryshkov pm_runtime_enable(&pdev->dev);
43387729e2aSDmitry Baryshkov
434e1072257SDmitry Baryshkov return msm_mdss;
43587729e2aSDmitry Baryshkov }
436ecb23f2eSDmitry Baryshkov
mdss_runtime_suspend(struct device * dev)437ecb23f2eSDmitry Baryshkov static int __maybe_unused mdss_runtime_suspend(struct device *dev)
438ecb23f2eSDmitry Baryshkov {
4396874f48bSDmitry Baryshkov struct msm_mdss *mdss = dev_get_drvdata(dev);
440ecb23f2eSDmitry Baryshkov
441ecb23f2eSDmitry Baryshkov DBG("");
442ecb23f2eSDmitry Baryshkov
4436874f48bSDmitry Baryshkov return msm_mdss_disable(mdss);
444ecb23f2eSDmitry Baryshkov }
445ecb23f2eSDmitry Baryshkov
mdss_runtime_resume(struct device * dev)446ecb23f2eSDmitry Baryshkov static int __maybe_unused mdss_runtime_resume(struct device *dev)
447ecb23f2eSDmitry Baryshkov {
4486874f48bSDmitry Baryshkov struct msm_mdss *mdss = dev_get_drvdata(dev);
449ecb23f2eSDmitry Baryshkov
450ecb23f2eSDmitry Baryshkov DBG("");
451ecb23f2eSDmitry Baryshkov
4526874f48bSDmitry Baryshkov return msm_mdss_enable(mdss);
453ecb23f2eSDmitry Baryshkov }
454ecb23f2eSDmitry Baryshkov
mdss_pm_suspend(struct device * dev)455ecb23f2eSDmitry Baryshkov static int __maybe_unused mdss_pm_suspend(struct device *dev)
456ecb23f2eSDmitry Baryshkov {
457ecb23f2eSDmitry Baryshkov
458ecb23f2eSDmitry Baryshkov if (pm_runtime_suspended(dev))
459ecb23f2eSDmitry Baryshkov return 0;
460ecb23f2eSDmitry Baryshkov
461ecb23f2eSDmitry Baryshkov return mdss_runtime_suspend(dev);
462ecb23f2eSDmitry Baryshkov }
463ecb23f2eSDmitry Baryshkov
mdss_pm_resume(struct device * dev)464ecb23f2eSDmitry Baryshkov static int __maybe_unused mdss_pm_resume(struct device *dev)
465ecb23f2eSDmitry Baryshkov {
466ecb23f2eSDmitry Baryshkov if (pm_runtime_suspended(dev))
467ecb23f2eSDmitry Baryshkov return 0;
468ecb23f2eSDmitry Baryshkov
469ecb23f2eSDmitry Baryshkov return mdss_runtime_resume(dev);
470ecb23f2eSDmitry Baryshkov }
471ecb23f2eSDmitry Baryshkov
472ecb23f2eSDmitry Baryshkov static const struct dev_pm_ops mdss_pm_ops = {
473ecb23f2eSDmitry Baryshkov SET_SYSTEM_SLEEP_PM_OPS(mdss_pm_suspend, mdss_pm_resume)
474ecb23f2eSDmitry Baryshkov SET_RUNTIME_PM_OPS(mdss_runtime_suspend, mdss_runtime_resume, NULL)
475ecb23f2eSDmitry Baryshkov };
476ecb23f2eSDmitry Baryshkov
mdss_probe(struct platform_device * pdev)477ecb23f2eSDmitry Baryshkov static int mdss_probe(struct platform_device *pdev)
478ecb23f2eSDmitry Baryshkov {
479ecb23f2eSDmitry Baryshkov struct msm_mdss *mdss;
4805d44531bSDmitry Baryshkov bool is_mdp5 = of_device_is_compatible(pdev->dev.of_node, "qcom,mdss");
481ecb23f2eSDmitry Baryshkov struct device *dev = &pdev->dev;
482ecb23f2eSDmitry Baryshkov int ret;
483ecb23f2eSDmitry Baryshkov
4845d44531bSDmitry Baryshkov mdss = msm_mdss_init(pdev, is_mdp5);
485ecb23f2eSDmitry Baryshkov if (IS_ERR(mdss))
486ecb23f2eSDmitry Baryshkov return PTR_ERR(mdss);
487ecb23f2eSDmitry Baryshkov
4886874f48bSDmitry Baryshkov platform_set_drvdata(pdev, mdss);
489ecb23f2eSDmitry Baryshkov
490ecb23f2eSDmitry Baryshkov /*
491ecb23f2eSDmitry Baryshkov * MDP5/DPU based devices don't have a flat hierarchy. There is a top
492ecb23f2eSDmitry Baryshkov * level parent: MDSS, and children: MDP5/DPU, DSI, HDMI, eDP etc.
493ecb23f2eSDmitry Baryshkov * Populate the children devices, find the MDP5/DPU node, and then add
494ecb23f2eSDmitry Baryshkov * the interfaces to our components list.
495ecb23f2eSDmitry Baryshkov */
496ecb23f2eSDmitry Baryshkov ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
497ecb23f2eSDmitry Baryshkov if (ret) {
498ecb23f2eSDmitry Baryshkov DRM_DEV_ERROR(dev, "failed to populate children devices\n");
4996874f48bSDmitry Baryshkov msm_mdss_destroy(mdss);
5006874f48bSDmitry Baryshkov return ret;
501ecb23f2eSDmitry Baryshkov }
502ecb23f2eSDmitry Baryshkov
503ecb23f2eSDmitry Baryshkov return 0;
504ecb23f2eSDmitry Baryshkov }
505ecb23f2eSDmitry Baryshkov
mdss_remove(struct platform_device * pdev)506ecb23f2eSDmitry Baryshkov static int mdss_remove(struct platform_device *pdev)
507ecb23f2eSDmitry Baryshkov {
5086874f48bSDmitry Baryshkov struct msm_mdss *mdss = platform_get_drvdata(pdev);
509ecb23f2eSDmitry Baryshkov
510ecb23f2eSDmitry Baryshkov of_platform_depopulate(&pdev->dev);
511ecb23f2eSDmitry Baryshkov
512ecb23f2eSDmitry Baryshkov msm_mdss_destroy(mdss);
513ecb23f2eSDmitry Baryshkov
514ecb23f2eSDmitry Baryshkov return 0;
515ecb23f2eSDmitry Baryshkov }
516ecb23f2eSDmitry Baryshkov
5176f410b24SDmitry Baryshkov static const struct msm_mdss_data msm8998_data = {
5186f410b24SDmitry Baryshkov .ubwc_enc_version = UBWC_1_0,
5196f410b24SDmitry Baryshkov .ubwc_dec_version = UBWC_1_0,
520c0666d1dSDmitry Baryshkov .highest_bank_bit = 2,
521aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
5226f410b24SDmitry Baryshkov };
5236f410b24SDmitry Baryshkov
5246f410b24SDmitry Baryshkov static const struct msm_mdss_data qcm2290_data = {
5256f410b24SDmitry Baryshkov /* no UBWC */
5266f410b24SDmitry Baryshkov .highest_bank_bit = 0x2,
527aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
5286f410b24SDmitry Baryshkov };
5296f410b24SDmitry Baryshkov
530d68db606SDmitry Baryshkov static const struct msm_mdss_data sc7180_data = {
531cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_2_0,
532d68db606SDmitry Baryshkov .ubwc_dec_version = UBWC_2_0,
533d68db606SDmitry Baryshkov .ubwc_static = 0x1e,
53488c232fdSAbhinav Kumar .highest_bank_bit = 0x1,
535aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
536d68db606SDmitry Baryshkov };
537d68db606SDmitry Baryshkov
538d68db606SDmitry Baryshkov static const struct msm_mdss_data sc7280_data = {
539cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_3_0,
540d68db606SDmitry Baryshkov .ubwc_dec_version = UBWC_4_0,
541d68db606SDmitry Baryshkov .ubwc_swizzle = 6,
542d68db606SDmitry Baryshkov .ubwc_static = 1,
543d68db606SDmitry Baryshkov .highest_bank_bit = 1,
544d68db606SDmitry Baryshkov .macrotile_mode = 1,
545aba75693SDmitry Baryshkov .reg_bus_bw = 74000,
546d68db606SDmitry Baryshkov };
547d68db606SDmitry Baryshkov
548aeff6bb5SDmitry Baryshkov static const struct msm_mdss_data sc8180x_data = {
549cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_3_0,
550aeff6bb5SDmitry Baryshkov .ubwc_dec_version = UBWC_3_0,
551aeff6bb5SDmitry Baryshkov .highest_bank_bit = 3,
552aeff6bb5SDmitry Baryshkov .macrotile_mode = 1,
553aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
554aeff6bb5SDmitry Baryshkov };
555aeff6bb5SDmitry Baryshkov
556d68db606SDmitry Baryshkov static const struct msm_mdss_data sc8280xp_data = {
557cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_4_0,
558d68db606SDmitry Baryshkov .ubwc_dec_version = UBWC_4_0,
559d68db606SDmitry Baryshkov .ubwc_swizzle = 6,
560d68db606SDmitry Baryshkov .ubwc_static = 1,
561d68db606SDmitry Baryshkov .highest_bank_bit = 2,
562d68db606SDmitry Baryshkov .macrotile_mode = 1,
563aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
564d68db606SDmitry Baryshkov };
565d68db606SDmitry Baryshkov
5669cffae4aSDmitry Baryshkov static const struct msm_mdss_data sdm845_data = {
567cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_2_0,
5689cffae4aSDmitry Baryshkov .ubwc_dec_version = UBWC_2_0,
5699cffae4aSDmitry Baryshkov .highest_bank_bit = 2,
570aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
5719cffae4aSDmitry Baryshkov };
5729cffae4aSDmitry Baryshkov
573c2c1217eSKonrad Dybcio static const struct msm_mdss_data sm6350_data = {
574cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_2_0,
575c2c1217eSKonrad Dybcio .ubwc_dec_version = UBWC_2_0,
576c2c1217eSKonrad Dybcio .ubwc_swizzle = 6,
577c2c1217eSKonrad Dybcio .ubwc_static = 0x1e,
578c2c1217eSKonrad Dybcio .highest_bank_bit = 1,
579aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
580c2c1217eSKonrad Dybcio };
581c2c1217eSKonrad Dybcio
582d68db606SDmitry Baryshkov static const struct msm_mdss_data sm8150_data = {
583cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_3_0,
584d68db606SDmitry Baryshkov .ubwc_dec_version = UBWC_3_0,
585d68db606SDmitry Baryshkov .highest_bank_bit = 2,
586aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
587d68db606SDmitry Baryshkov };
588d68db606SDmitry Baryshkov
589d68db606SDmitry Baryshkov static const struct msm_mdss_data sm6115_data = {
590cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_1_0,
591d68db606SDmitry Baryshkov .ubwc_dec_version = UBWC_2_0,
592d68db606SDmitry Baryshkov .ubwc_swizzle = 7,
593d68db606SDmitry Baryshkov .ubwc_static = 0x11f,
5946f410b24SDmitry Baryshkov .highest_bank_bit = 0x1,
595aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
596d68db606SDmitry Baryshkov };
597d68db606SDmitry Baryshkov
59887aa3c9bSMarijn Suijten static const struct msm_mdss_data sm6125_data = {
599cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_1_0,
60087aa3c9bSMarijn Suijten .ubwc_dec_version = UBWC_3_0,
60187aa3c9bSMarijn Suijten .ubwc_swizzle = 1,
60287aa3c9bSMarijn Suijten .highest_bank_bit = 1,
603*ab7554fbSDmitry Baryshkov .reg_bus_bw = 76800,
604d68db606SDmitry Baryshkov };
605d68db606SDmitry Baryshkov
606d68db606SDmitry Baryshkov static const struct msm_mdss_data sm8250_data = {
607cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_4_0,
608d68db606SDmitry Baryshkov .ubwc_dec_version = UBWC_4_0,
609d68db606SDmitry Baryshkov .ubwc_swizzle = 6,
610d68db606SDmitry Baryshkov .ubwc_static = 1,
611d68db606SDmitry Baryshkov /* TODO: highest_bank_bit = 2 for LP_DDR4 */
612d68db606SDmitry Baryshkov .highest_bank_bit = 3,
613d68db606SDmitry Baryshkov .macrotile_mode = 1,
614aba75693SDmitry Baryshkov .reg_bus_bw = 76800,
615aba75693SDmitry Baryshkov };
616aba75693SDmitry Baryshkov
617aba75693SDmitry Baryshkov static const struct msm_mdss_data sm8350_data = {
618aba75693SDmitry Baryshkov .ubwc_enc_version = UBWC_4_0,
619aba75693SDmitry Baryshkov .ubwc_dec_version = UBWC_4_0,
620aba75693SDmitry Baryshkov .ubwc_swizzle = 6,
621aba75693SDmitry Baryshkov .ubwc_static = 1,
622aba75693SDmitry Baryshkov /* TODO: highest_bank_bit = 2 for LP_DDR4 */
623aba75693SDmitry Baryshkov .highest_bank_bit = 3,
624aba75693SDmitry Baryshkov .macrotile_mode = 1,
625aba75693SDmitry Baryshkov .reg_bus_bw = 74000,
626d68db606SDmitry Baryshkov };
627d68db606SDmitry Baryshkov
628a85c238cSDmitry Baryshkov static const struct msm_mdss_data sm8550_data = {
629cab5b406SDmitry Baryshkov .ubwc_enc_version = UBWC_4_0,
630a85c238cSDmitry Baryshkov .ubwc_dec_version = UBWC_4_3,
631a85c238cSDmitry Baryshkov .ubwc_swizzle = 6,
632a85c238cSDmitry Baryshkov .ubwc_static = 1,
633a85c238cSDmitry Baryshkov /* TODO: highest_bank_bit = 2 for LP_DDR4 */
634a85c238cSDmitry Baryshkov .highest_bank_bit = 3,
635a85c238cSDmitry Baryshkov .macrotile_mode = 1,
636aba75693SDmitry Baryshkov .reg_bus_bw = 57000,
637a85c238cSDmitry Baryshkov };
638ecb23f2eSDmitry Baryshkov static const struct of_device_id mdss_dt_match[] = {
6395d44531bSDmitry Baryshkov { .compatible = "qcom,mdss" },
6406f410b24SDmitry Baryshkov { .compatible = "qcom,msm8998-mdss", .data = &msm8998_data },
6416f410b24SDmitry Baryshkov { .compatible = "qcom,qcm2290-mdss", .data = &qcm2290_data },
6429cffae4aSDmitry Baryshkov { .compatible = "qcom,sdm845-mdss", .data = &sdm845_data },
643d68db606SDmitry Baryshkov { .compatible = "qcom,sc7180-mdss", .data = &sc7180_data },
644d68db606SDmitry Baryshkov { .compatible = "qcom,sc7280-mdss", .data = &sc7280_data },
645aeff6bb5SDmitry Baryshkov { .compatible = "qcom,sc8180x-mdss", .data = &sc8180x_data },
646d68db606SDmitry Baryshkov { .compatible = "qcom,sc8280xp-mdss", .data = &sc8280xp_data },
647d68db606SDmitry Baryshkov { .compatible = "qcom,sm6115-mdss", .data = &sm6115_data },
64887aa3c9bSMarijn Suijten { .compatible = "qcom,sm6125-mdss", .data = &sm6125_data },
649c2c1217eSKonrad Dybcio { .compatible = "qcom,sm6350-mdss", .data = &sm6350_data },
6505ff3d3a0SKonrad Dybcio { .compatible = "qcom,sm6375-mdss", .data = &sm6350_data },
651d68db606SDmitry Baryshkov { .compatible = "qcom,sm8150-mdss", .data = &sm8150_data },
652d68db606SDmitry Baryshkov { .compatible = "qcom,sm8250-mdss", .data = &sm8250_data },
653aba75693SDmitry Baryshkov { .compatible = "qcom,sm8350-mdss", .data = &sm8350_data },
654aba75693SDmitry Baryshkov { .compatible = "qcom,sm8450-mdss", .data = &sm8350_data },
655a85c238cSDmitry Baryshkov { .compatible = "qcom,sm8550-mdss", .data = &sm8550_data },
656ecb23f2eSDmitry Baryshkov {}
657ecb23f2eSDmitry Baryshkov };
658ecb23f2eSDmitry Baryshkov MODULE_DEVICE_TABLE(of, mdss_dt_match);
659ecb23f2eSDmitry Baryshkov
660ecb23f2eSDmitry Baryshkov static struct platform_driver mdss_platform_driver = {
661ecb23f2eSDmitry Baryshkov .probe = mdss_probe,
662ecb23f2eSDmitry Baryshkov .remove = mdss_remove,
663ecb23f2eSDmitry Baryshkov .driver = {
664ecb23f2eSDmitry Baryshkov .name = "msm-mdss",
665ecb23f2eSDmitry Baryshkov .of_match_table = mdss_dt_match,
666ecb23f2eSDmitry Baryshkov .pm = &mdss_pm_ops,
667ecb23f2eSDmitry Baryshkov },
668ecb23f2eSDmitry Baryshkov };
669ecb23f2eSDmitry Baryshkov
msm_mdss_register(void)670ecb23f2eSDmitry Baryshkov void __init msm_mdss_register(void)
671ecb23f2eSDmitry Baryshkov {
672ecb23f2eSDmitry Baryshkov platform_driver_register(&mdss_platform_driver);
673ecb23f2eSDmitry Baryshkov }
674ecb23f2eSDmitry Baryshkov
msm_mdss_unregister(void)675ecb23f2eSDmitry Baryshkov void __exit msm_mdss_unregister(void)
676ecb23f2eSDmitry Baryshkov {
677ecb23f2eSDmitry Baryshkov platform_driver_unregister(&mdss_platform_driver);
678ecb23f2eSDmitry Baryshkov }
679