cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_panel.c (10012B)


      1/*
      2 * Copyright (C) 2013, NVIDIA Corporation.  All rights reserved.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice (including the
     12 * next paragraph) shall be included in all copies or substantial portions
     13 * of the Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 * DEALINGS IN THE SOFTWARE.
     22 */
     23
     24#include <linux/backlight.h>
     25#include <linux/err.h>
     26#include <linux/module.h>
     27
     28#include <drm/drm_crtc.h>
     29#include <drm/drm_panel.h>
     30#include <drm/drm_print.h>
     31
     32static DEFINE_MUTEX(panel_lock);
     33static LIST_HEAD(panel_list);
     34
     35/**
     36 * DOC: drm panel
     37 *
     38 * The DRM panel helpers allow drivers to register panel objects with a
     39 * central registry and provide functions to retrieve those panels in display
     40 * drivers.
     41 *
     42 * For easy integration into drivers using the &drm_bridge infrastructure please
     43 * take look at drm_panel_bridge_add() and devm_drm_panel_bridge_add().
     44 */
     45
     46/**
     47 * drm_panel_init - initialize a panel
     48 * @panel: DRM panel
     49 * @dev: parent device of the panel
     50 * @funcs: panel operations
     51 * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to
     52 *	the panel interface
     53 *
     54 * Initialize the panel structure for subsequent registration with
     55 * drm_panel_add().
     56 */
     57void drm_panel_init(struct drm_panel *panel, struct device *dev,
     58		    const struct drm_panel_funcs *funcs, int connector_type)
     59{
     60	INIT_LIST_HEAD(&panel->list);
     61	panel->dev = dev;
     62	panel->funcs = funcs;
     63	panel->connector_type = connector_type;
     64}
     65EXPORT_SYMBOL(drm_panel_init);
     66
     67/**
     68 * drm_panel_add - add a panel to the global registry
     69 * @panel: panel to add
     70 *
     71 * Add a panel to the global registry so that it can be looked up by display
     72 * drivers.
     73 */
     74void drm_panel_add(struct drm_panel *panel)
     75{
     76	mutex_lock(&panel_lock);
     77	list_add_tail(&panel->list, &panel_list);
     78	mutex_unlock(&panel_lock);
     79}
     80EXPORT_SYMBOL(drm_panel_add);
     81
     82/**
     83 * drm_panel_remove - remove a panel from the global registry
     84 * @panel: DRM panel
     85 *
     86 * Removes a panel from the global registry.
     87 */
     88void drm_panel_remove(struct drm_panel *panel)
     89{
     90	mutex_lock(&panel_lock);
     91	list_del_init(&panel->list);
     92	mutex_unlock(&panel_lock);
     93}
     94EXPORT_SYMBOL(drm_panel_remove);
     95
     96/**
     97 * drm_panel_prepare - power on a panel
     98 * @panel: DRM panel
     99 *
    100 * Calling this function will enable power and deassert any reset signals to
    101 * the panel. After this has completed it is possible to communicate with any
    102 * integrated circuitry via a command bus.
    103 *
    104 * Return: 0 on success or a negative error code on failure.
    105 */
    106int drm_panel_prepare(struct drm_panel *panel)
    107{
    108	if (!panel)
    109		return -EINVAL;
    110
    111	if (panel->funcs && panel->funcs->prepare)
    112		return panel->funcs->prepare(panel);
    113
    114	return 0;
    115}
    116EXPORT_SYMBOL(drm_panel_prepare);
    117
    118/**
    119 * drm_panel_unprepare - power off a panel
    120 * @panel: DRM panel
    121 *
    122 * Calling this function will completely power off a panel (assert the panel's
    123 * reset, turn off power supplies, ...). After this function has completed, it
    124 * is usually no longer possible to communicate with the panel until another
    125 * call to drm_panel_prepare().
    126 *
    127 * Return: 0 on success or a negative error code on failure.
    128 */
    129int drm_panel_unprepare(struct drm_panel *panel)
    130{
    131	if (!panel)
    132		return -EINVAL;
    133
    134	if (panel->funcs && panel->funcs->unprepare)
    135		return panel->funcs->unprepare(panel);
    136
    137	return 0;
    138}
    139EXPORT_SYMBOL(drm_panel_unprepare);
    140
    141/**
    142 * drm_panel_enable - enable a panel
    143 * @panel: DRM panel
    144 *
    145 * Calling this function will cause the panel display drivers to be turned on
    146 * and the backlight to be enabled. Content will be visible on screen after
    147 * this call completes.
    148 *
    149 * Return: 0 on success or a negative error code on failure.
    150 */
    151int drm_panel_enable(struct drm_panel *panel)
    152{
    153	int ret;
    154
    155	if (!panel)
    156		return -EINVAL;
    157
    158	if (panel->funcs && panel->funcs->enable) {
    159		ret = panel->funcs->enable(panel);
    160		if (ret < 0)
    161			return ret;
    162	}
    163
    164	ret = backlight_enable(panel->backlight);
    165	if (ret < 0)
    166		DRM_DEV_INFO(panel->dev, "failed to enable backlight: %d\n",
    167			     ret);
    168
    169	return 0;
    170}
    171EXPORT_SYMBOL(drm_panel_enable);
    172
    173/**
    174 * drm_panel_disable - disable a panel
    175 * @panel: DRM panel
    176 *
    177 * This will typically turn off the panel's backlight or disable the display
    178 * drivers. For smart panels it should still be possible to communicate with
    179 * the integrated circuitry via any command bus after this call.
    180 *
    181 * Return: 0 on success or a negative error code on failure.
    182 */
    183int drm_panel_disable(struct drm_panel *panel)
    184{
    185	int ret;
    186
    187	if (!panel)
    188		return -EINVAL;
    189
    190	ret = backlight_disable(panel->backlight);
    191	if (ret < 0)
    192		DRM_DEV_INFO(panel->dev, "failed to disable backlight: %d\n",
    193			     ret);
    194
    195	if (panel->funcs && panel->funcs->disable)
    196		return panel->funcs->disable(panel);
    197
    198	return 0;
    199}
    200EXPORT_SYMBOL(drm_panel_disable);
    201
    202/**
    203 * drm_panel_get_modes - probe the available display modes of a panel
    204 * @panel: DRM panel
    205 * @connector: DRM connector
    206 *
    207 * The modes probed from the panel are automatically added to the connector
    208 * that the panel is attached to.
    209 *
    210 * Return: The number of modes available from the panel on success or a
    211 * negative error code on failure.
    212 */
    213int drm_panel_get_modes(struct drm_panel *panel,
    214			struct drm_connector *connector)
    215{
    216	if (!panel)
    217		return -EINVAL;
    218
    219	if (panel->funcs && panel->funcs->get_modes)
    220		return panel->funcs->get_modes(panel, connector);
    221
    222	return -EOPNOTSUPP;
    223}
    224EXPORT_SYMBOL(drm_panel_get_modes);
    225
    226#ifdef CONFIG_OF
    227/**
    228 * of_drm_find_panel - look up a panel using a device tree node
    229 * @np: device tree node of the panel
    230 *
    231 * Searches the set of registered panels for one that matches the given device
    232 * tree node. If a matching panel is found, return a pointer to it.
    233 *
    234 * Return: A pointer to the panel registered for the specified device tree
    235 * node or an ERR_PTR() if no panel matching the device tree node can be found.
    236 *
    237 * Possible error codes returned by this function:
    238 *
    239 * - EPROBE_DEFER: the panel device has not been probed yet, and the caller
    240 *   should retry later
    241 * - ENODEV: the device is not available (status != "okay" or "ok")
    242 */
    243struct drm_panel *of_drm_find_panel(const struct device_node *np)
    244{
    245	struct drm_panel *panel;
    246
    247	if (!of_device_is_available(np))
    248		return ERR_PTR(-ENODEV);
    249
    250	mutex_lock(&panel_lock);
    251
    252	list_for_each_entry(panel, &panel_list, list) {
    253		if (panel->dev->of_node == np) {
    254			mutex_unlock(&panel_lock);
    255			return panel;
    256		}
    257	}
    258
    259	mutex_unlock(&panel_lock);
    260	return ERR_PTR(-EPROBE_DEFER);
    261}
    262EXPORT_SYMBOL(of_drm_find_panel);
    263
    264/**
    265 * of_drm_get_panel_orientation - look up the orientation of the panel through
    266 * the "rotation" binding from a device tree node
    267 * @np: device tree node of the panel
    268 * @orientation: orientation enum to be filled in
    269 *
    270 * Looks up the rotation of a panel in the device tree. The orientation of the
    271 * panel is expressed as a property name "rotation" in the device tree. The
    272 * rotation in the device tree is counter clockwise.
    273 *
    274 * Return: 0 when a valid rotation value (0, 90, 180, or 270) is read or the
    275 * rotation property doesn't exist. Return a negative error code on failure.
    276 */
    277int of_drm_get_panel_orientation(const struct device_node *np,
    278				 enum drm_panel_orientation *orientation)
    279{
    280	int rotation, ret;
    281
    282	ret = of_property_read_u32(np, "rotation", &rotation);
    283	if (ret == -EINVAL) {
    284		/* Don't return an error if there's no rotation property. */
    285		*orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
    286		return 0;
    287	}
    288
    289	if (ret < 0)
    290		return ret;
    291
    292	if (rotation == 0)
    293		*orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
    294	else if (rotation == 90)
    295		*orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
    296	else if (rotation == 180)
    297		*orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
    298	else if (rotation == 270)
    299		*orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
    300	else
    301		return -EINVAL;
    302
    303	return 0;
    304}
    305EXPORT_SYMBOL(of_drm_get_panel_orientation);
    306#endif
    307
    308#if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE)
    309/**
    310 * drm_panel_of_backlight - use backlight device node for backlight
    311 * @panel: DRM panel
    312 *
    313 * Use this function to enable backlight handling if your panel
    314 * uses device tree and has a backlight phandle.
    315 *
    316 * When the panel is enabled backlight will be enabled after a
    317 * successful call to &drm_panel_funcs.enable()
    318 *
    319 * When the panel is disabled backlight will be disabled before the
    320 * call to &drm_panel_funcs.disable().
    321 *
    322 * A typical implementation for a panel driver supporting device tree
    323 * will call this function at probe time. Backlight will then be handled
    324 * transparently without requiring any intervention from the driver.
    325 * drm_panel_of_backlight() must be called after the call to drm_panel_init().
    326 *
    327 * Return: 0 on success or a negative error code on failure.
    328 */
    329int drm_panel_of_backlight(struct drm_panel *panel)
    330{
    331	struct backlight_device *backlight;
    332
    333	if (!panel || !panel->dev)
    334		return -EINVAL;
    335
    336	backlight = devm_of_find_backlight(panel->dev);
    337
    338	if (IS_ERR(backlight))
    339		return PTR_ERR(backlight);
    340
    341	panel->backlight = backlight;
    342	return 0;
    343}
    344EXPORT_SYMBOL(drm_panel_of_backlight);
    345#endif
    346
    347MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
    348MODULE_DESCRIPTION("DRM panel infrastructure");
    349MODULE_LICENSE("GPL and additional rights");