cregit-Linux how code gets into the kernel

Release 4.11 drivers/gpu/drm/imx/imx-drm-core.c

/*
 * Freescale i.MX drm driver
 *
 * Copyright (C) 2011 Sascha Hauer, Pengutronix
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
#include <linux/component.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_of.h>
#include <video/imx-ipu-v3.h>

#include "imx-drm.h"


#define MAX_CRTC	4


struct imx_drm_component {
	
struct device_node *of_node;
	
struct list_head list;
};


struct imx_drm_device {
	
struct drm_device			*drm;
	
struct imx_drm_crtc			*crtc[MAX_CRTC];
	
unsigned int				pipes;
	
struct drm_fbdev_cma			*fbhelper;
	
struct drm_atomic_state			*state;
};


struct imx_drm_crtc {
	
struct drm_crtc				*crtc;
	
struct imx_drm_crtc_helper_funcs	imx_drm_helper_funcs;
};

#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)

static int legacyfb_depth = 16;
module_param(legacyfb_depth, int, 0444);
#endif


static void imx_drm_driver_lastclose(struct drm_device *drm) { struct imx_drm_device *imxdrm = drm->dev_private; drm_fbdev_cma_restore_mode(imxdrm->fbhelper); }

Contributors

PersonTokensPropCommitsCommitProp
Sascha Hauer27100.00%1100.00%
Total27100.00%1100.00%


static int imx_drm_enable_vblank(struct drm_device *drm, unsigned int pipe) { struct imx_drm_device *imxdrm = drm->dev_private; struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe]; int ret; if (!imx_drm_crtc) return -EINVAL; if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank) return -ENOSYS; ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank( imx_drm_crtc->crtc); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Sascha Hauer6888.31%133.33%
Russell King67.79%133.33%
Thierry Reding33.90%133.33%
Total77100.00%3100.00%


static void imx_drm_disable_vblank(struct drm_device *drm, unsigned int pipe) { struct imx_drm_device *imxdrm = drm->dev_private; struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe]; if (!imx_drm_crtc) return; if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank) return; imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); }

Contributors

PersonTokensPropCommitsCommitProp
Sascha Hauer5587.30%133.33%
Russell King57.94%133.33%
Thierry Reding34.76%133.33%
Total63100.00%3100.00%

static const struct file_operations imx_drm_driver_fops = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, .unlocked_ioctl = drm_ioctl, .mmap = drm_gem_cma_mmap, .poll = drm_poll, .read = drm_read, .llseek = noop_llseek, };
void imx_drm_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); drm_connector_cleanup(connector); }

Contributors

PersonTokensPropCommitsCommitProp
Sascha Hauer1155.00%133.33%
Russell King840.00%133.33%
Thomas Wood15.00%133.33%
Total20100.00%3100.00%

EXPORT_SYMBOL_GPL(imx_drm_connector_destroy);
void imx_drm_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King1280.00%150.00%
Sascha Hauer320.00%150.00%
Total15100.00%2100.00%

EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy);
static void imx_drm_output_poll_changed(struct drm_device *drm) { struct imx_drm_device *imxdrm = drm->dev_private; drm_fbdev_cma_hotplug_event(imxdrm->fbhelper); }

Contributors

PersonTokensPropCommitsCommitProp
Russell King27100.00%1100.00%
Total27100.00%1100.00%


static int imx_drm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { int ret; ret = drm_atomic_helper_check_modeset(dev, state); if (ret) return ret; ret = drm_atomic_helper_check_planes(dev, state); if (ret) return ret; /* * Check modeset again in case crtc_state->mode_changed is * updated in plane's ->atomic_check callback. */ ret = drm_atomic_helper_check_modeset(dev, state); if (ret) return ret; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Liu Ying71100.00%1100.00%
Total71100.00%1100.00%

static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = { .fb_create = drm_fb_cma_create, .output_poll_changed = imx_drm_output_poll_changed, .atomic_check = imx_drm_atomic_check, .atomic_commit = drm_atomic_helper_commit, };
static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; drm_atomic_helper_commit_modeset_disables(dev, state); drm_atomic_helper_commit_planes(dev, state, DRM_PLANE_COMMIT_ACTIVE_ONLY | DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET); drm_atomic_helper_commit_modeset_enables(dev, state); drm_atomic_helper_commit_hw_done(state); drm_atomic_helper_wait_for_vblanks(dev, state); drm_atomic_helper_cleanup_planes(dev, state); }

Contributors

PersonTokensPropCommitsCommitProp
Liu Ying4671.88%375.00%
Lucas Stach1828.12%125.00%
Total64100.00%4100.00%

static struct drm_mode_config_helper_funcs imx_drm_mode_config_helpers = { .atomic_commit_tail = imx_drm_atomic_commit_tail, }; /* * imx_drm_add_crtc - add a new crtc */
int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, struct imx_drm_crtc **new_crtc, struct drm_plane *primary_plane, const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, struct device_node *port) { struct imx_drm_device *imxdrm = drm->dev_private; struct imx_drm_crtc *imx_drm_crtc; /* * The vblank arrays are dimensioned by MAX_CRTC - we can't * pass IDs greater than this to those functions. */ if (imxdrm->pipes >= MAX_CRTC) return -EINVAL; if (imxdrm->drm->open_count) return -EBUSY; imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL); if (!imx_drm_crtc) return -ENOMEM; imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; imx_drm_crtc->crtc = crtc; crtc->port = port; imxdrm->crtc[imxdrm->pipes++] = imx_drm_crtc; *new_crtc = imx_drm_crtc; drm_crtc_helper_add(crtc, imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL, imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs, NULL); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Lucas Stach10864.67%120.00%
Russell King3923.35%240.00%
Sascha Hauer1710.18%120.00%
Liu Ying31.80%120.00%
Total167100.00%5100.00%

EXPORT_SYMBOL_GPL(imx_drm_add_crtc); /* * imx_drm_remove_crtc - remove a crtc */
int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) { struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private; unsigned int pipe = drm_crtc_index(imx_drm_crtc->crtc); drm_crtc_cleanup(imx_drm_crtc->crtc); imxdrm->crtc[pipe] = NULL; kfree(imx_drm_crtc); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sascha Hauer2543.10%125.00%
Russell King2237.93%250.00%
Thierry Reding1118.97%125.00%
Total58100.00%4100.00%

EXPORT_SYMBOL_GPL(imx_drm_remove_crtc);
int imx_drm_encoder_parse_of(struct drm_device *drm, struct drm_encoder *encoder, struct device_node *np) { uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np); /* * If we failed to find the CRTC(s) which this encoder is * supposed to be connected to, it's because the CRTC has * not been registered yet. Defer probing, and hope that * the required CRTC is added later. */ if (crtc_mask == 0) return -EPROBE_DEFER; encoder->possible_crtcs = crtc_mask; /* FIXME: this is the mask of outputs which can clone this output. */ encoder->possible_clones = ~0; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King4272.41%250.00%
Philipp Zabel1220.69%125.00%
Sascha Hauer46.90%125.00%
Total58100.00%4100.00%

EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); static const struct drm_ioctl_desc imx_drm_ioctls[] = { /* none so far */ }; static struct drm_driver imx_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, .lastclose = imx_drm_driver_lastclose, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = drm_gem_prime_import, .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, .gem_prime_vunmap = drm_gem_cma_prime_vunmap, .gem_prime_mmap = drm_gem_cma_prime_mmap, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = imx_drm_enable_vblank, .disable_vblank = imx_drm_disable_vblank, .ioctls = imx_drm_ioctls, .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), .fops = &imx_drm_driver_fops, .name = "imx-drm", .desc = "i.MX DRM graphics", .date = "20120507", .major = 1, .minor = 0, .patchlevel = 0, };
static int compare_of(struct device *dev, void *data) { struct device_node *np = data; /* Special case for DI, dev->of_node may not be set yet */ if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) { struct ipu_client_platformdata *pdata = dev->platform_data; return pdata->of_node == np; } /* Special case for LDB, one device for two channels */ if (of_node_cmp(np->name, "lvds-channel") == 0) { np = of_get_parent(np); of_node_put(np); } return dev->of_node == np; }

Contributors

PersonTokensPropCommitsCommitProp
Lucas Stach6773.63%125.00%
Russell King1819.78%125.00%
Philipp Zabel66.59%250.00%
Total91100.00%4100.00%


static int imx_drm_bind(struct device *dev) { struct drm_device *drm; struct imx_drm_device *imxdrm; int ret; drm = drm_dev_alloc(&imx_drm_driver, dev); if (IS_ERR(drm)) return PTR_ERR(drm); imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL); if (!imxdrm) { ret = -ENOMEM; goto err_unref; } imxdrm->drm = drm; drm->dev_private = imxdrm; /* * enable drm irq mode. * - with irq_enabled = true, we can use the vblank feature. * * P.S. note that we wouldn't use drm irq handler but * just specific driver own one instead because * drm framework supports only one irq handler and * drivers can well take care of their interrupts */ drm->irq_enabled = true; /* * set max width and height as default value(4096x4096). * this value would be used to check framebuffer size limitation * at drm_mode_addfb(). */ drm->mode_config.min_width = 1; drm->mode_config.min_height = 1; drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; drm->mode_config.funcs = &imx_drm_mode_config_funcs; drm->mode_config.helper_private = &imx_drm_mode_config_helpers; drm_mode_config_init(drm); ret = drm_vblank_init(drm, MAX_CRTC); if (ret) goto err_kms; dev_set_drvdata(dev, drm); /* Now try and bind all our sub-components */ ret = component_bind_all(dev, drm); if (ret) goto err_vblank; drm_mode_config_reset(drm); /* * All components are now initialised, so setup the fb helper. * The fb helper takes copies of key hardware information, so the * crtcs/connectors/encoders must not change after this point. */ #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) if (legacyfb_depth != 16 && legacyfb_depth != 32) { dev_warn(dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); legacyfb_depth = 16; } imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, MAX_CRTC); if (IS_ERR(imxdrm->fbhelper)) { ret = PTR_ERR(imxdrm->fbhelper); imxdrm->fbhelper = NULL; goto err_unbind; } #endif drm_kms_helper_poll_init(drm); ret = drm_dev_register(drm, 0); if (ret) goto err_fbhelper; return 0; err_fbhelper: drm_kms_helper_poll_fini(drm); #if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) if (imxdrm->fbhelper) drm_fbdev_cma_fini(imxdrm->fbhelper); err_unbind: #endif component_unbind_all(drm->dev, drm); err_vblank: drm_vblank_cleanup(drm); err_kms: drm_mode_config_cleanup(drm); err_unref: drm_dev_unref(drm); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Lucas Stach31287.15%114.29%
Philipp Zabel215.87%342.86%
Russell King102.79%114.29%
Arnd Bergmann82.23%114.29%
Dan Carpenter71.96%114.29%
Total358100.00%7100.00%


static void imx_drm_unbind(struct device *dev) { struct drm_device *drm = dev_get_drvdata(dev); struct imx_drm_device *imxdrm = drm->dev_private; drm_dev_unregister(drm); drm_kms_helper_poll_fini(drm); if (imxdrm->fbhelper) drm_fbdev_cma_fini(imxdrm->fbhelper); drm_mode_config_cleanup(drm); component_unbind_all(drm->dev, drm); dev_set_drvdata(dev, NULL); drm_dev_unref(drm); }

Contributors

PersonTokensPropCommitsCommitProp
Lucas Stach6278.48%266.67%
Russell King1721.52%133.33%
Total79100.00%3100.00%

static const struct component_master_ops imx_drm_ops = { .bind = imx_drm_bind, .unbind = imx_drm_unbind, };
static int imx_drm_platform_probe(struct platform_device *pdev) { int ret = drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops); if (!ret) ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Russell King2244.00%233.33%
Sascha Hauer1122.00%116.67%
Philipp Zabel816.00%116.67%
Liviu Dudau510.00%116.67%
Shawn Guo48.00%116.67%
Total50100.00%6100.00%


static int imx_drm_platform_remove(struct platform_device *pdev) { component_master_del(&pdev->dev, &imx_drm_ops); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sascha Hauer1768.00%133.33%
Russell King728.00%133.33%
Daniel Vetter14.00%133.33%
Total25100.00%3100.00%

#ifdef CONFIG_PM_SLEEP
static int imx_drm_suspend(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct imx_drm_device *imxdrm; /* The drm_dev is NULL before .load hook is called */ if (drm_dev == NULL) return 0; drm_kms_helper_poll_disable(drm_dev); imxdrm = drm_dev->dev_private; imxdrm->state = drm_atomic_helper_suspend(drm_dev); if (IS_ERR(imxdrm->state)) { drm_kms_helper_poll_enable(drm_dev); return PTR_ERR(imxdrm->state); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Liu Ying4453.01%150.00%
Shawn Guo3946.99%150.00%
Total83100.00%2100.00%


static int imx_drm_resume(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); struct imx_drm_device *imx_drm; if (drm_dev == NULL) return 0; imx_drm = drm_dev->dev_private; drm_atomic_helper_resume(drm_dev, imx_drm->state); drm_kms_helper_poll_enable(drm_dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo4272.41%150.00%
Liu Ying1627.59%150.00%
Total58100.00%2100.00%

#endif static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume); static const struct of_device_id imx_drm_dt_ids[] = { { .compatible = "fsl,imx-display-subsystem", }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, imx_drm_dt_ids); static struct platform_driver imx_drm_pdrv = { .probe = imx_drm_platform_probe, .remove = imx_drm_platform_remove, .driver = { .name = "imx-drm", .pm = &imx_drm_pm_ops, .of_match_table = imx_drm_dt_ids, }, }; module_platform_driver(imx_drm_pdrv); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); MODULE_DESCRIPTION("i.MX drm driver core"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Lucas Stach59630.90%37.32%
Sascha Hauer50326.08%12.44%
Russell King33117.16%1126.83%
Liu Ying20710.73%512.20%
Philipp Zabel1296.69%49.76%
Shawn Guo1065.50%24.88%
Thierry Reding180.93%37.32%
Arnd Bergmann80.41%12.44%
Archit Taneja80.41%12.44%
Dan Carpenter70.36%12.44%
Daniel Vetter60.31%49.76%
Liviu Dudau50.26%12.44%
Fabio Estevam20.10%12.44%
Ville Syrjälä10.05%12.44%
Thomas Wood10.05%12.44%
Marek Vašut10.05%12.44%
Total1929100.00%41100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.