cregit-Linux how code gets into the kernel

Release 4.18 drivers/gpu/drm/rockchip/rockchip_drm_psr.c

/*
 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
 * Author: Yakir Yang <ykk@rock-chips.com>
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * 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 <drm/drmP.h>
#include <drm/drm_crtc_helper.h>

#include "rockchip_drm_drv.h"
#include "rockchip_drm_psr.h"


#define PSR_FLUSH_TIMEOUT_MS	100


struct psr_drv {
	
struct list_head	list;
	
struct drm_encoder	*encoder;

	
struct mutex		lock;
	
int			inhibit_count;
	
bool			enabled;

	
struct delayed_work	flush_work;

	
int (*set)(struct drm_encoder *encoder, bool enable);
};


static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder) { struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; struct psr_drv *psr; mutex_lock(&drm_drv->psr_list_lock); list_for_each_entry(psr, &drm_drv->psr_list, list) { if (psr->encoder == encoder) goto out; } psr = ERR_PTR(-ENODEV); out: mutex_unlock(&drm_drv->psr_list_lock); return psr; }

Contributors

PersonTokensPropCommitsCommitProp
Zain Wang7797.47%150.00%
Sean Paul22.53%150.00%
Total79100.00%2100.00%


static int psr_set_state_locked(struct psr_drv *psr, bool enable) { int ret; if (psr->inhibit_count > 0) return -EINVAL; if (enable == psr->enabled) return 0; ret = psr->set(psr->encoder, enable); if (ret) return ret; psr->enabled = enable; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Tomasz Figa3043.48%228.57%
Yakir Yang2637.68%114.29%
Sean Paul710.14%342.86%
Zain Wang68.70%114.29%
Total69100.00%7100.00%


static void psr_flush_handler(struct work_struct *work) { struct psr_drv *psr = container_of(to_delayed_work(work), struct psr_drv, flush_work); mutex_lock(&psr->lock); psr_set_state_locked(psr, true); mutex_unlock(&psr->lock); }

Contributors

PersonTokensPropCommitsCommitProp
Sean Paul2751.92%240.00%
Yakir Yang1834.62%120.00%
Kees Cook611.54%120.00%
Tomasz Figa11.92%120.00%
Total52100.00%5100.00%

/** * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder * @encoder: encoder to obtain the PSR encoder * * Decrements PSR inhibit count on given encoder. Should be called only * for a PSR inhibit count increment done before. If PSR inhibit counter * reaches zero, PSR flush work is scheduled to make the hardware enter * PSR mode in PSR_FLUSH_TIMEOUT_MS. * * Returns: * Zero on success, negative errno on failure. */
int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder) { struct psr_drv *psr = find_psr_by_encoder(encoder); if (IS_ERR(psr)) return PTR_ERR(psr); mutex_lock(&psr->lock); --psr->inhibit_count; WARN_ON(psr->inhibit_count < 0); if (!psr->inhibit_count) mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS); mutex_unlock(&psr->lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Yakir Yang3541.18%120.00%
Tomasz Figa3136.47%120.00%
Sean Paul1517.65%240.00%
Zain Wang44.71%120.00%
Total85100.00%5100.00%

EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put); /** * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder * @encoder: encoder to obtain the PSR encoder * * Increments PSR inhibit count on given encoder. This function guarantees * that after it returns PSR is turned off on given encoder and no PSR-related * hardware state change occurs at least until a matching call to * rockchip_drm_psr_inhibit_put() is done. * * Returns: * Zero on success, negative errno on failure. */
int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder) { struct psr_drv *psr = find_psr_by_encoder(encoder); if (IS_ERR(psr)) return PTR_ERR(psr); mutex_lock(&psr->lock); psr_set_state_locked(psr, false); ++psr->inhibit_count; mutex_unlock(&psr->lock); cancel_delayed_work_sync(&psr->flush_work); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Sean Paul3143.06%233.33%
Yakir Yang2737.50%116.67%
Tomasz Figa1013.89%233.33%
Zain Wang45.56%116.67%
Total72100.00%6100.00%

EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get);
static void rockchip_drm_do_flush(struct psr_drv *psr) { cancel_delayed_work_sync(&psr->flush_work); mutex_lock(&psr->lock); if (!psr_set_state_locked(psr, false)) mod_delayed_work(system_wq, &psr->flush_work, PSR_FLUSH_TIMEOUT_MS); mutex_unlock(&psr->lock); }

Contributors

PersonTokensPropCommitsCommitProp
Tomasz Figa3052.63%125.00%
Sean Paul2442.11%250.00%
Yakir Yang35.26%125.00%
Total57100.00%4100.00%

/** * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders * @dev: drm device * * Disable the PSR function for all registered encoders, and then enable the * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been * changed during flush time, then keep the state no change after flush * timeout. * * Returns: * Zero on success, negative errno on failure. */
void rockchip_drm_psr_flush_all(struct drm_device *dev) { struct rockchip_drm_private *drm_drv = dev->dev_private; struct psr_drv *psr; mutex_lock(&drm_drv->psr_list_lock); list_for_each_entry(psr, &drm_drv->psr_list, list) rockchip_drm_do_flush(psr); mutex_unlock(&drm_drv->psr_list_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Yakir Yang3566.04%125.00%
Sean Paul1833.96%375.00%
Total53100.00%4100.00%

EXPORT_SYMBOL(rockchip_drm_psr_flush_all); /** * rockchip_drm_psr_register - register encoder to psr driver * @encoder: encoder that obtain the PSR function * @psr_set: call back to set PSR state * * The function returns with PSR inhibit counter initialized with one * and the caller (typically encoder driver) needs to call * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR * enable request. * * Returns: * Zero on success, negative errno on failure. */
int rockchip_drm_psr_register(struct drm_encoder *encoder, int (*psr_set)(struct drm_encoder *, bool enable)) { struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; struct psr_drv *psr; if (!encoder || !psr_set) return -EINVAL; psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL); if (!psr) return -ENOMEM; INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler); mutex_init(&psr->lock); psr->inhibit_count = 1; psr->enabled = false; psr->encoder = encoder; psr->set = psr_set; mutex_lock(&drm_drv->psr_list_lock); list_add_tail(&psr->list, &drm_drv->psr_list); mutex_unlock(&drm_drv->psr_list_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Yakir Yang12584.46%112.50%
Sean Paul1812.16%450.00%
Tomasz Figa42.70%225.00%
Zain Wang10.68%112.50%
Total148100.00%8100.00%

EXPORT_SYMBOL(rockchip_drm_psr_register); /** * rockchip_drm_psr_unregister - unregister encoder to psr driver * @encoder: encoder that obtain the PSR function * @psr_set: call back to set PSR state * * It is expected that the PSR inhibit counter is 1 when this function is * called, which corresponds to a state when related encoder has been * disconnected from any CRTCs and its driver called * rockchip_drm_psr_inhibit_get() to stop the PSR logic. * * Returns: * Zero on success, negative errno on failure. */
void rockchip_drm_psr_unregister(struct drm_encoder *encoder) { struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; struct psr_drv *psr, *n; mutex_lock(&drm_drv->psr_list_lock); list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { if (psr->encoder == encoder) { /* * Any other value would mean that the encoder * is still in use. */ WARN_ON(psr->inhibit_count != 1); list_del(&psr->list); kfree(psr); } } mutex_unlock(&drm_drv->psr_list_lock); }

Contributors

PersonTokensPropCommitsCommitProp
Yakir Yang8190.00%125.00%
Tomasz Figa55.56%125.00%
Sean Paul44.44%250.00%
Total90100.00%4100.00%

EXPORT_SYMBOL(rockchip_drm_psr_unregister);

Overall Contributors

PersonTokensPropCommitsCommitProp
Yakir Yang41452.08%18.33%
Sean Paul16120.25%650.00%
Tomasz Figa12115.22%216.67%
Zain Wang9311.70%216.67%
Kees Cook60.75%18.33%
Total795100.00%12100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.