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 static int komeda_register_open(struct inode
*inode
, struct file
*filp
)
46 return single_open(filp
, komeda_register_show
, inode
->i_private
);
49 static const struct file_operations komeda_register_fops
= {
51 .open
= komeda_register_open
,
54 .release
= single_release
,
57 #ifdef CONFIG_DEBUG_FS
58 static void komeda_debugfs_init(struct komeda_dev
*mdev
)
60 if (!debugfs_initialized())
63 mdev
->debugfs_root
= debugfs_create_dir("komeda", NULL
);
64 debugfs_create_file("register", 0444, mdev
->debugfs_root
,
65 mdev
, &komeda_register_fops
);
66 debugfs_create_x16("err_verbosity", 0664, mdev
->debugfs_root
,
67 &mdev
->err_verbosity
);
72 core_id_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
74 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
76 return snprintf(buf
, PAGE_SIZE
, "0x%08x\n", mdev
->chip
.core_id
);
78 static DEVICE_ATTR_RO(core_id
);
81 config_id_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
83 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
84 struct komeda_pipeline
*pipe
= mdev
->pipelines
[0];
85 union komeda_config_id config_id
;
88 memset(&config_id
, 0, sizeof(config_id
));
90 config_id
.max_line_sz
= pipe
->layers
[0]->hsize_in
.end
;
91 config_id
.n_pipelines
= mdev
->n_pipelines
;
92 config_id
.n_scalers
= pipe
->n_scalers
;
93 config_id
.n_layers
= pipe
->n_layers
;
94 config_id
.n_richs
= 0;
95 for (i
= 0; i
< pipe
->n_layers
; i
++) {
96 if (pipe
->layers
[i
]->layer_type
== KOMEDA_FMT_RICH_LAYER
)
99 return snprintf(buf
, PAGE_SIZE
, "0x%08x\n", config_id
.value
);
101 static DEVICE_ATTR_RO(config_id
);
104 aclk_hz_show(struct device
*dev
, struct device_attribute
*attr
, char *buf
)
106 struct komeda_dev
*mdev
= dev_to_mdev(dev
);
108 return snprintf(buf
, PAGE_SIZE
, "%lu\n", clk_get_rate(mdev
->aclk
));
110 static DEVICE_ATTR_RO(aclk_hz
);
112 static struct attribute
*komeda_sysfs_entries
[] = {
113 &dev_attr_core_id
.attr
,
114 &dev_attr_config_id
.attr
,
115 &dev_attr_aclk_hz
.attr
,
119 static struct attribute_group komeda_sysfs_attr_group
= {
120 .attrs
= komeda_sysfs_entries
,
123 static int komeda_parse_pipe_dt(struct komeda_pipeline
*pipe
)
125 struct device_node
*np
= pipe
->of_node
;
128 clk
= of_clk_get_by_name(np
, "pxclk");
130 DRM_ERROR("get pxclk for pipeline %d failed!\n", pipe
->id
);
136 pipe
->of_output_links
[0] =
137 of_graph_get_remote_node(np
, KOMEDA_OF_PORT_OUTPUT
, 0);
138 pipe
->of_output_links
[1] =
139 of_graph_get_remote_node(np
, KOMEDA_OF_PORT_OUTPUT
, 1);
140 pipe
->of_output_port
=
141 of_graph_get_port_by_id(np
, KOMEDA_OF_PORT_OUTPUT
);
143 pipe
->dual_link
= pipe
->of_output_links
[0] && pipe
->of_output_links
[1];
148 static int komeda_parse_dt(struct device
*dev
, struct komeda_dev
*mdev
)
150 struct platform_device
*pdev
= to_platform_device(dev
);
151 struct device_node
*child
, *np
= dev
->of_node
;
152 struct komeda_pipeline
*pipe
;
153 u32 pipe_id
= U32_MAX
;
156 mdev
->irq
= platform_get_irq(pdev
, 0);
158 DRM_ERROR("could not get IRQ number.\n");
162 /* Get the optional framebuffer memory resource */
163 ret
= of_reserved_mem_device_init(dev
);
164 if (ret
&& ret
!= -ENODEV
)
168 for_each_available_child_of_node(np
, child
) {
169 if (of_node_name_eq(child
, "pipeline")) {
170 of_property_read_u32(child
, "reg", &pipe_id
);
171 if (pipe_id
>= mdev
->n_pipelines
) {
172 DRM_WARN("Skip the redundant DT node: pipeline-%u.\n",
176 mdev
->pipelines
[pipe_id
]->of_node
= of_node_get(child
);
180 for (pipe_id
= 0; pipe_id
< mdev
->n_pipelines
; pipe_id
++) {
181 pipe
= mdev
->pipelines
[pipe_id
];
183 if (!pipe
->of_node
) {
184 DRM_ERROR("Pipeline-%d doesn't have a DT node.\n",
188 ret
= komeda_parse_pipe_dt(pipe
);
196 struct komeda_dev
*komeda_dev_create(struct device
*dev
)
198 struct platform_device
*pdev
= to_platform_device(dev
);
199 komeda_identify_func komeda_identify
;
200 struct komeda_dev
*mdev
;
203 komeda_identify
= of_device_get_match_data(dev
);
204 if (!komeda_identify
)
205 return ERR_PTR(-ENODEV
);
207 mdev
= devm_kzalloc(dev
, sizeof(*mdev
), GFP_KERNEL
);
209 return ERR_PTR(-ENOMEM
);
211 mutex_init(&mdev
->lock
);
214 mdev
->reg_base
= devm_platform_ioremap_resource(pdev
, 0);
215 if (IS_ERR(mdev
->reg_base
)) {
216 DRM_ERROR("Map register space failed.\n");
217 err
= PTR_ERR(mdev
->reg_base
);
218 mdev
->reg_base
= NULL
;
222 mdev
->aclk
= devm_clk_get(dev
, "aclk");
223 if (IS_ERR(mdev
->aclk
)) {
224 DRM_ERROR("Get engine clk failed.\n");
225 err
= PTR_ERR(mdev
->aclk
);
230 clk_prepare_enable(mdev
->aclk
);
232 mdev
->funcs
= komeda_identify(mdev
->reg_base
, &mdev
->chip
);
234 DRM_ERROR("Failed to identify the HW.\n");
239 DRM_INFO("Found ARM Mali-D%x version r%dp%d\n",
240 MALIDP_CORE_ID_PRODUCT_ID(mdev
->chip
.core_id
),
241 MALIDP_CORE_ID_MAJOR(mdev
->chip
.core_id
),
242 MALIDP_CORE_ID_MINOR(mdev
->chip
.core_id
));
244 mdev
->funcs
->init_format_table(mdev
);
246 err
= mdev
->funcs
->enum_resources(mdev
);
248 DRM_ERROR("enumerate display resource failed.\n");
252 err
= komeda_parse_dt(dev
, mdev
);
254 DRM_ERROR("parse device tree failed.\n");
258 err
= komeda_assemble_pipelines(mdev
);
260 DRM_ERROR("assemble display pipelines failed.\n");
264 dev
->dma_parms
= &mdev
->dma_parms
;
265 dma_set_max_seg_size(dev
, DMA_BIT_MASK(32));
267 mdev
->iommu
= iommu_get_domain_for_dev(mdev
->dev
);
269 DRM_INFO("continue without IOMMU support!\n");
271 clk_disable_unprepare(mdev
->aclk
);
273 err
= sysfs_create_group(&dev
->kobj
, &komeda_sysfs_attr_group
);
275 DRM_ERROR("create sysfs group failed.\n");
279 mdev
->err_verbosity
= KOMEDA_DEV_PRINT_ERR_EVENTS
;
281 #ifdef CONFIG_DEBUG_FS
282 komeda_debugfs_init(mdev
);
288 clk_disable_unprepare(mdev
->aclk
);
290 komeda_dev_destroy(mdev
);
294 void komeda_dev_destroy(struct komeda_dev
*mdev
)
296 struct device
*dev
= mdev
->dev
;
297 const struct komeda_dev_funcs
*funcs
= mdev
->funcs
;
300 sysfs_remove_group(&dev
->kobj
, &komeda_sysfs_attr_group
);
302 #ifdef CONFIG_DEBUG_FS
303 debugfs_remove_recursive(mdev
->debugfs_root
);
307 clk_prepare_enable(mdev
->aclk
);
309 for (i
= 0; i
< mdev
->n_pipelines
; i
++) {
310 komeda_pipeline_destroy(mdev
, mdev
->pipelines
[i
]);
311 mdev
->pipelines
[i
] = NULL
;
314 mdev
->n_pipelines
= 0;
316 of_reserved_mem_device_release(dev
);
318 if (funcs
&& funcs
->cleanup
)
319 funcs
->cleanup(mdev
);
321 if (mdev
->reg_base
) {
322 devm_iounmap(dev
, mdev
->reg_base
);
323 mdev
->reg_base
= NULL
;
327 clk_disable_unprepare(mdev
->aclk
);
328 devm_clk_put(dev
, mdev
->aclk
);
332 devm_kfree(dev
, mdev
);
335 int komeda_dev_resume(struct komeda_dev
*mdev
)
337 clk_prepare_enable(mdev
->aclk
);
339 mdev
->funcs
->enable_irq(mdev
);
341 if (mdev
->iommu
&& mdev
->funcs
->connect_iommu
)
342 if (mdev
->funcs
->connect_iommu(mdev
))
343 DRM_ERROR("connect iommu failed.\n");
348 int komeda_dev_suspend(struct komeda_dev
*mdev
)
350 if (mdev
->iommu
&& mdev
->funcs
->disconnect_iommu
)
351 if (mdev
->funcs
->disconnect_iommu(mdev
))
352 DRM_ERROR("disconnect iommu failed.\n");
354 mdev
->funcs
->disable_irq(mdev
);
356 clk_disable_unprepare(mdev
->aclk
);