Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.3-rc8 226 lines 5.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * ARC PGU DRM driver. 4 * 5 * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) 6 */ 7 8#include <linux/clk.h> 9#include <drm/drm_atomic_helper.h> 10#include <drm/drm_debugfs.h> 11#include <drm/drm_device.h> 12#include <drm/drm_drv.h> 13#include <drm/drm_fb_cma_helper.h> 14#include <drm/drm_fb_helper.h> 15#include <drm/drm_gem_cma_helper.h> 16#include <drm/drm_gem_framebuffer_helper.h> 17#include <drm/drm_probe_helper.h> 18#include <linux/dma-mapping.h> 19#include <linux/module.h> 20#include <linux/of_reserved_mem.h> 21#include <linux/platform_device.h> 22 23#include "arcpgu.h" 24#include "arcpgu_regs.h" 25 26static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { 27 .fb_create = drm_gem_fb_create, 28 .atomic_check = drm_atomic_helper_check, 29 .atomic_commit = drm_atomic_helper_commit, 30}; 31 32static void arcpgu_setup_mode_config(struct drm_device *drm) 33{ 34 drm_mode_config_init(drm); 35 drm->mode_config.min_width = 0; 36 drm->mode_config.min_height = 0; 37 drm->mode_config.max_width = 1920; 38 drm->mode_config.max_height = 1080; 39 drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs; 40} 41 42DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops); 43 44static int arcpgu_load(struct drm_device *drm) 45{ 46 struct platform_device *pdev = to_platform_device(drm->dev); 47 struct arcpgu_drm_private *arcpgu; 48 struct device_node *encoder_node; 49 struct resource *res; 50 int ret; 51 52 arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL); 53 if (arcpgu == NULL) 54 return -ENOMEM; 55 56 drm->dev_private = arcpgu; 57 58 arcpgu->clk = devm_clk_get(drm->dev, "pxlclk"); 59 if (IS_ERR(arcpgu->clk)) 60 return PTR_ERR(arcpgu->clk); 61 62 arcpgu_setup_mode_config(drm); 63 64 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 65 arcpgu->regs = devm_ioremap_resource(&pdev->dev, res); 66 if (IS_ERR(arcpgu->regs)) 67 return PTR_ERR(arcpgu->regs); 68 69 dev_info(drm->dev, "arc_pgu ID: 0x%x\n", 70 arc_pgu_read(arcpgu, ARCPGU_REG_ID)); 71 72 /* Get the optional framebuffer memory resource */ 73 ret = of_reserved_mem_device_init(drm->dev); 74 if (ret && ret != -ENODEV) 75 return ret; 76 77 if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32))) 78 return -ENODEV; 79 80 if (arc_pgu_setup_crtc(drm) < 0) 81 return -ENODEV; 82 83 /* find the encoder node and initialize it */ 84 encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0); 85 if (encoder_node) { 86 ret = arcpgu_drm_hdmi_init(drm, encoder_node); 87 of_node_put(encoder_node); 88 if (ret < 0) 89 return ret; 90 } else { 91 ret = arcpgu_drm_sim_init(drm, NULL); 92 if (ret < 0) 93 return ret; 94 } 95 96 drm_mode_config_reset(drm); 97 drm_kms_helper_poll_init(drm); 98 99 platform_set_drvdata(pdev, drm); 100 return 0; 101} 102 103static int arcpgu_unload(struct drm_device *drm) 104{ 105 drm_kms_helper_poll_fini(drm); 106 drm_atomic_helper_shutdown(drm); 107 drm_mode_config_cleanup(drm); 108 109 return 0; 110} 111 112#ifdef CONFIG_DEBUG_FS 113static int arcpgu_show_pxlclock(struct seq_file *m, void *arg) 114{ 115 struct drm_info_node *node = (struct drm_info_node *)m->private; 116 struct drm_device *drm = node->minor->dev; 117 struct arcpgu_drm_private *arcpgu = drm->dev_private; 118 unsigned long clkrate = clk_get_rate(arcpgu->clk); 119 unsigned long mode_clock = arcpgu->crtc.mode.crtc_clock * 1000; 120 121 seq_printf(m, "hw : %lu\n", clkrate); 122 seq_printf(m, "mode: %lu\n", mode_clock); 123 return 0; 124} 125 126static struct drm_info_list arcpgu_debugfs_list[] = { 127 { "clocks", arcpgu_show_pxlclock, 0 }, 128}; 129 130static int arcpgu_debugfs_init(struct drm_minor *minor) 131{ 132 return drm_debugfs_create_files(arcpgu_debugfs_list, 133 ARRAY_SIZE(arcpgu_debugfs_list), minor->debugfs_root, minor); 134} 135#endif 136 137static struct drm_driver arcpgu_drm_driver = { 138 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | 139 DRIVER_ATOMIC, 140 .name = "arcpgu", 141 .desc = "ARC PGU Controller", 142 .date = "20160219", 143 .major = 1, 144 .minor = 0, 145 .patchlevel = 0, 146 .fops = &arcpgu_drm_ops, 147 .dumb_create = drm_gem_cma_dumb_create, 148 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 149 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 150 .gem_free_object_unlocked = drm_gem_cma_free_object, 151 .gem_print_info = drm_gem_cma_print_info, 152 .gem_vm_ops = &drm_gem_cma_vm_ops, 153 .gem_prime_export = drm_gem_prime_export, 154 .gem_prime_import = drm_gem_prime_import, 155 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 156 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 157 .gem_prime_vmap = drm_gem_cma_prime_vmap, 158 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 159 .gem_prime_mmap = drm_gem_cma_prime_mmap, 160#ifdef CONFIG_DEBUG_FS 161 .debugfs_init = arcpgu_debugfs_init, 162#endif 163}; 164 165static int arcpgu_probe(struct platform_device *pdev) 166{ 167 struct drm_device *drm; 168 int ret; 169 170 drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev); 171 if (IS_ERR(drm)) 172 return PTR_ERR(drm); 173 174 ret = arcpgu_load(drm); 175 if (ret) 176 goto err_unref; 177 178 ret = drm_dev_register(drm, 0); 179 if (ret) 180 goto err_unload; 181 182 drm_fbdev_generic_setup(drm, 16); 183 184 return 0; 185 186err_unload: 187 arcpgu_unload(drm); 188 189err_unref: 190 drm_dev_put(drm); 191 192 return ret; 193} 194 195static int arcpgu_remove(struct platform_device *pdev) 196{ 197 struct drm_device *drm = platform_get_drvdata(pdev); 198 199 drm_dev_unregister(drm); 200 arcpgu_unload(drm); 201 drm_dev_put(drm); 202 203 return 0; 204} 205 206static const struct of_device_id arcpgu_of_table[] = { 207 {.compatible = "snps,arcpgu"}, 208 {} 209}; 210 211MODULE_DEVICE_TABLE(of, arcpgu_of_table); 212 213static struct platform_driver arcpgu_platform_driver = { 214 .probe = arcpgu_probe, 215 .remove = arcpgu_remove, 216 .driver = { 217 .name = "arcpgu", 218 .of_match_table = arcpgu_of_table, 219 }, 220}; 221 222module_platform_driver(arcpgu_platform_driver); 223 224MODULE_AUTHOR("Carlos Palminha <palminha@synopsys.com>"); 225MODULE_DESCRIPTION("ARC PGU DRM driver"); 226MODULE_LICENSE("GPL");