1 // SPDX-License-Identifier: GPL-2.0
3 * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4 * Author: James.Qian.Wang <james.qian.wang@arm.com>
8 #include <linux/iommu.h>
9 #include <linux/of_device.h>
10 #include <linux/of_graph.h>
11 #include <linux/of_reserved_mem.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/dma-mapping.h>
15 #ifdef CONFIG_DEBUG_FS
16 #include <linux/debugfs.h>
17 #include <linux/seq_file.h>
20 #include <drm/drm_print.h>
22 #include "komeda_dev.h"
24 static int komeda_register_show(struct seq_file
*sf
, void *x
)
26 struct komeda_dev
*mdev
= sf
->private;
29 seq_puts(sf
, "\n====== Komeda register dump =========\n");
31 pm_runtime_get_sync(mdev
->dev
);
33 if (mdev
->funcs
->dump_register
)
34 mdev
->funcs
->dump_register(mdev
, sf
);
36 for (i
= 0; i
< mdev
->n_pipelines
; i
++)
37 komeda_pipeline_dump_register(mdev
->pipelines
[i
], sf
);
39 pm_runtime_put(mdev
->dev
);
44 DEFINE_SHOW_ATTRIBUTE(komeda_register
);
46 #ifdef CONFIG_DEBUG_FS
47 static void komeda_debugfs_init(struct komeda_dev
*mdev
)
49 if (!debugfs_initialized())
52 mdev
->debugfs_root
= debugfs_create_dir("komeda", NULL
);
53 debugfs_create_file("register", 0444, mdev
->debugfs_root
,
54 mdev
, &komeda_register_fops
);
55 debugfs_create_x16("err_verbosity", 0664, mdev
->debugfs_root
,
56 &mdev
->err_verbosity
);
61 core_id_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
63 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
65 return snprintf(buf
, PAGE_SIZE
, "0x%08x\n", mdev
->chip
.core_id
);
67 static DEVICE_ATTR_RO(core_id
);
70 config_id_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
72 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
73 struct komeda_pipeline
*pipe
= mdev
->pipelines
[0];
74 union komeda_config_id config_id
;
77 memset(&config_id
, 0, sizeof(config_id
));
79 config_id
.max_line_sz
= pipe
->layers
[0]->hsize_in
.end
;
80 config_id
.n_pipelines
= mdev
->n_pipelines
;
81 config_id
.n_scalers
= pipe
->n_scalers
;
82 config_id
.n_layers
= pipe
->n_layers
;
83 config_id
.n_richs
= 0;
84 for (i
= 0; i
< pipe
->n_layers
; i
++) {
85 if (pipe
->layers
[i
]->layer_type
== KOMEDA_FMT_RICH_LAYER
)
88 return snprintf(buf
, PAGE_SIZE
, "0x%08x\n", config_id
.value
);
90 static DEVICE_ATTR_RO(config_id
);
93 aclk_hz_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
95 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
97 return snprintf(buf
, PAGE_SIZE
, "%lu\n", clk_get_rate(mdev
->aclk
));
99 static DEVICE_ATTR_RO(aclk_hz
);
101 static struct attribute
*komeda_sysfs_entries
[] = {
102 &dev_attr_core_id
.attr
,
103 &dev_attr_config_id
.attr
,
104 &dev_attr_aclk_hz
.attr
,
108 static struct attribute_group komeda_sysfs_attr_group
= {
109 .attrs
= komeda_sysfs_entries
,
112 static int komeda_parse_pipe_dt(struct komeda_pipeline
*pipe
)
114 struct device_node
*np
= pipe
->of_node
;
117 clk
= of_clk_get_by_name(np
, "pxclk");
119 DRM_ERROR("get pxclk for pipeline %d failed!\n", pipe
->id
);
125 pipe
->of_output_links
[0] =
126 of_graph_get_remote_node(np
, KOMEDA_OF_PORT_OUTPUT
, 0);
127 pipe
->of_output_links
[1] =
128 of_graph_get_remote_node(np
, KOMEDA_OF_PORT_OUTPUT
, 1);
129 pipe
->of_output_port
=
130 of_graph_get_port_by_id(np
, KOMEDA_OF_PORT_OUTPUT
);
132 pipe
->dual_link
= pipe
->of_output_links
[0] && pipe
->of_output_links
[1];
137 static int komeda_parse_dt(struct device
*dev
, struct komeda_dev
*mdev
)
139 struct platform_device
*pdev
= to_platform_device(dev
);
140 struct device_node
*child
, *np
= dev
->of_node
;
141 struct komeda_pipeline
*pipe
;
142 u32 pipe_id
= U32_MAX
;
145 mdev
->irq
= platform_get_irq(pdev
, 0);
147 DRM_ERROR("could not get IRQ number.\n");
151 /* Get the optional framebuffer memory resource */
152 ret
= of_reserved_mem_device_init(dev
);
153 if (ret
&& ret
!= -ENODEV
)
156 for_each_available_child_of_node(np
, child
) {
157 if (of_node_name_eq(child
, "pipeline")) {
158 of_property_read_u32(child
, "reg", &pipe_id
);
159 if (pipe_id
>= mdev
->n_pipelines
) {
160 DRM_WARN("Skip the redundant DT node: pipeline-%u.\n",
164 mdev
->pipelines
[pipe_id
]->of_node
= of_node_get(child
);
168 for (pipe_id
= 0; pipe_id
< mdev
->n_pipelines
; pipe_id
++) {
169 pipe
= mdev
->pipelines
[pipe_id
];
171 if (!pipe
->of_node
) {
172 DRM_ERROR("Pipeline-%d doesn't have a DT node.\n",
176 ret
= komeda_parse_pipe_dt(pipe
);
184 struct komeda_dev
*komeda_dev_create(struct device
*dev
)
186 struct platform_device
*pdev
= to_platform_device(dev
);
187 komeda_identify_func komeda_identify
;
188 struct komeda_dev
*mdev
;
191 komeda_identify
= of_device_get_match_data(dev
);
192 if (!komeda_identify
)
193 return ERR_PTR(-ENODEV
);
195 mdev
= devm_kzalloc(dev
, sizeof(*mdev
), GFP_KERNEL
);
197 return ERR_PTR(-ENOMEM
);
199 mutex_init(&mdev
->lock
);
202 mdev
->reg_base
= devm_platform_ioremap_resource(pdev
, 0);
203 if (IS_ERR(mdev
->reg_base
)) {
204 DRM_ERROR("Map register space failed.\n");
205 err
= PTR_ERR(mdev
->reg_base
);
206 mdev
->reg_base
= NULL
;
210 mdev
->aclk
= devm_clk_get(dev
, "aclk");
211 if (IS_ERR(mdev
->aclk
)) {
212 DRM_ERROR("Get engine clk failed.\n");
213 err
= PTR_ERR(mdev
->aclk
);
218 clk_prepare_enable(mdev
->aclk
);
220 mdev
->funcs
= komeda_identify(mdev
->reg_base
, &mdev
->chip
);
222 DRM_ERROR("Failed to identify the HW.\n");
227 DRM_INFO("Found ARM Mali-D%x version r%dp%d\n",
228 MALIDP_CORE_ID_PRODUCT_ID(mdev
->chip
.core_id
),
229 MALIDP_CORE_ID_MAJOR(mdev
->chip
.core_id
),
230 MALIDP_CORE_ID_MINOR(mdev
->chip
.core_id
));
232 mdev
->funcs
->init_format_table(mdev
);
234 err
= mdev
->funcs
->enum_resources(mdev
);
236 DRM_ERROR("enumerate display resource failed.\n");
240 err
= komeda_parse_dt(dev
, mdev
);
242 DRM_ERROR("parse device tree failed.\n");
246 err
= komeda_assemble_pipelines(mdev
);
248 DRM_ERROR("assemble display pipelines failed.\n");
252 dma_set_max_seg_size(dev
, U32_MAX
);
254 mdev
->iommu
= iommu_get_domain_for_dev(mdev
->dev
);
256 DRM_INFO("continue without IOMMU support!\n");
258 clk_disable_unprepare(mdev
->aclk
);
260 err
= sysfs_create_group(&dev
->kobj
, &komeda_sysfs_attr_group
);
262 DRM_ERROR("create sysfs group failed.\n");
266 mdev
->err_verbosity
= KOMEDA_DEV_PRINT_ERR_EVENTS
;
268 #ifdef CONFIG_DEBUG_FS
269 komeda_debugfs_init(mdev
);
275 clk_disable_unprepare(mdev
->aclk
);
277 komeda_dev_destroy(mdev
);
281 void komeda_dev_destroy(struct komeda_dev
*mdev
)
283 struct device
*dev
= mdev
->dev
;
284 const struct komeda_dev_funcs
*funcs
= mdev
->funcs
;
287 sysfs_remove_group(&dev
->kobj
, &komeda_sysfs_attr_group
);
289 #ifdef CONFIG_DEBUG_FS
290 debugfs_remove_recursive(mdev
->debugfs_root
);
294 clk_prepare_enable(mdev
->aclk
);
296 for (i
= 0; i
< mdev
->n_pipelines
; i
++) {
297 komeda_pipeline_destroy(mdev
, mdev
->pipelines
[i
]);
298 mdev
->pipelines
[i
] = NULL
;
301 mdev
->n_pipelines
= 0;
303 of_reserved_mem_device_release(dev
);
305 if (funcs
&& funcs
->cleanup
)
306 funcs
->cleanup(mdev
);
308 if (mdev
->reg_base
) {
309 devm_iounmap(dev
, mdev
->reg_base
);
310 mdev
->reg_base
= NULL
;
314 clk_disable_unprepare(mdev
->aclk
);
315 devm_clk_put(dev
, mdev
->aclk
);
319 devm_kfree(dev
, mdev
);
322 int komeda_dev_resume(struct komeda_dev
*mdev
)
324 clk_prepare_enable(mdev
->aclk
);
326 mdev
->funcs
->enable_irq(mdev
);
328 if (mdev
->iommu
&& mdev
->funcs
->connect_iommu
)
329 if (mdev
->funcs
->connect_iommu(mdev
))
330 DRM_ERROR("connect iommu failed.\n");
335 int komeda_dev_suspend(struct komeda_dev
*mdev
)
337 if (mdev
->iommu
&& mdev
->funcs
->disconnect_iommu
)
338 if (mdev
->funcs
->disconnect_iommu(mdev
))
339 DRM_ERROR("disconnect iommu failed.\n");
341 mdev
->funcs
->disable_irq(mdev
);
343 clk_disable_unprepare(mdev
->aclk
);