162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2016 Intel Corporation 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, distribute, and sell this software and its 562306a36Sopenharmony_ci * documentation for any purpose is hereby granted without fee, provided that 662306a36Sopenharmony_ci * the above copyright notice appear in all copies and that both that copyright 762306a36Sopenharmony_ci * notice and this permission notice appear in supporting documentation, and 862306a36Sopenharmony_ci * that the name of the copyright holders not be used in advertising or 962306a36Sopenharmony_ci * publicity pertaining to distribution of the software without specific, 1062306a36Sopenharmony_ci * written prior permission. The copyright holders make no representations 1162306a36Sopenharmony_ci * about the suitability of this software for any purpose. It is provided "as 1262306a36Sopenharmony_ci * is" without express or implied warranty. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1562306a36Sopenharmony_ci * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1662306a36Sopenharmony_ci * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1762306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1862306a36Sopenharmony_ci * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1962306a36Sopenharmony_ci * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2062306a36Sopenharmony_ci * OF THIS SOFTWARE. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#ifndef __DRM_ENCODER_H__ 2462306a36Sopenharmony_ci#define __DRM_ENCODER_H__ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/list.h> 2762306a36Sopenharmony_ci#include <linux/ctype.h> 2862306a36Sopenharmony_ci#include <drm/drm_crtc.h> 2962306a36Sopenharmony_ci#include <drm/drm_mode.h> 3062306a36Sopenharmony_ci#include <drm/drm_mode_object.h> 3162306a36Sopenharmony_ci#include <drm/drm_util.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistruct drm_encoder; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/** 3662306a36Sopenharmony_ci * struct drm_encoder_funcs - encoder controls 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * Encoders sit between CRTCs and connectors. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_cistruct drm_encoder_funcs { 4162306a36Sopenharmony_ci /** 4262306a36Sopenharmony_ci * @reset: 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Reset encoder hardware and software state to off. This function isn't 4562306a36Sopenharmony_ci * called by the core directly, only through drm_mode_config_reset(). 4662306a36Sopenharmony_ci * It's not a helper hook only for historical reasons. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci void (*reset)(struct drm_encoder *encoder); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /** 5162306a36Sopenharmony_ci * @destroy: 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * Clean up encoder resources. This is only called at driver unload time 5462306a36Sopenharmony_ci * through drm_mode_config_cleanup() since an encoder cannot be 5562306a36Sopenharmony_ci * hotplugged in DRM. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_ci void (*destroy)(struct drm_encoder *encoder); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci /** 6062306a36Sopenharmony_ci * @late_register: 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * This optional hook can be used to register additional userspace 6362306a36Sopenharmony_ci * interfaces attached to the encoder like debugfs interfaces. 6462306a36Sopenharmony_ci * It is called late in the driver load sequence from drm_dev_register(). 6562306a36Sopenharmony_ci * Everything added from this callback should be unregistered in 6662306a36Sopenharmony_ci * the early_unregister callback. 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci * Returns: 6962306a36Sopenharmony_ci * 7062306a36Sopenharmony_ci * 0 on success, or a negative error code on failure. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ci int (*late_register)(struct drm_encoder *encoder); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /** 7562306a36Sopenharmony_ci * @early_unregister: 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * This optional hook should be used to unregister the additional 7862306a36Sopenharmony_ci * userspace interfaces attached to the encoder from 7962306a36Sopenharmony_ci * @late_register. It is called from drm_dev_unregister(), 8062306a36Sopenharmony_ci * early in the driver unload sequence to disable userspace access 8162306a36Sopenharmony_ci * before data structures are torndown. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci void (*early_unregister)(struct drm_encoder *encoder); 8462306a36Sopenharmony_ci}; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/** 8762306a36Sopenharmony_ci * struct drm_encoder - central DRM encoder structure 8862306a36Sopenharmony_ci * @dev: parent DRM device 8962306a36Sopenharmony_ci * @head: list management 9062306a36Sopenharmony_ci * @base: base KMS object 9162306a36Sopenharmony_ci * @name: human readable name, can be overwritten by the driver 9262306a36Sopenharmony_ci * @funcs: control functions, can be NULL for simple managed encoders 9362306a36Sopenharmony_ci * @helper_private: mid-layer private data 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * CRTCs drive pixels to encoders, which convert them into signals 9662306a36Sopenharmony_ci * appropriate for a given connector or set of connectors. 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_cistruct drm_encoder { 9962306a36Sopenharmony_ci struct drm_device *dev; 10062306a36Sopenharmony_ci struct list_head head; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci struct drm_mode_object base; 10362306a36Sopenharmony_ci char *name; 10462306a36Sopenharmony_ci /** 10562306a36Sopenharmony_ci * @encoder_type: 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci * One of the DRM_MODE_ENCODER_<foo> types in drm_mode.h. The following 10862306a36Sopenharmony_ci * encoder types are defined thus far: 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * - DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A. 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * - DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort. 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * - DRM_MODE_ENCODER_LVDS for display panels, or in general any panel 11562306a36Sopenharmony_ci * with a proprietary parallel connector. 11662306a36Sopenharmony_ci * 11762306a36Sopenharmony_ci * - DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video, 11862306a36Sopenharmony_ci * Component, SCART). 11962306a36Sopenharmony_ci * 12062306a36Sopenharmony_ci * - DRM_MODE_ENCODER_VIRTUAL for virtual machine displays 12162306a36Sopenharmony_ci * 12262306a36Sopenharmony_ci * - DRM_MODE_ENCODER_DSI for panels connected using the DSI serial bus. 12362306a36Sopenharmony_ci * 12462306a36Sopenharmony_ci * - DRM_MODE_ENCODER_DPI for panels connected using the DPI parallel 12562306a36Sopenharmony_ci * bus. 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * - DRM_MODE_ENCODER_DPMST for special fake encoders used to allow 12862306a36Sopenharmony_ci * mutliple DP MST streams to share one physical encoder. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ci int encoder_type; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /** 13362306a36Sopenharmony_ci * @index: Position inside the mode_config.list, can be used as an array 13462306a36Sopenharmony_ci * index. It is invariant over the lifetime of the encoder. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_ci unsigned index; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /** 13962306a36Sopenharmony_ci * @possible_crtcs: Bitmask of potential CRTC bindings, using 14062306a36Sopenharmony_ci * drm_crtc_index() as the index into the bitfield. The driver must set 14162306a36Sopenharmony_ci * the bits for all &drm_crtc objects this encoder can be connected to 14262306a36Sopenharmony_ci * before calling drm_dev_register(). 14362306a36Sopenharmony_ci * 14462306a36Sopenharmony_ci * You will get a WARN if you get this wrong in the driver. 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * Note that since CRTC objects can't be hotplugged the assigned indices 14762306a36Sopenharmony_ci * are stable and hence known before registering all objects. 14862306a36Sopenharmony_ci */ 14962306a36Sopenharmony_ci uint32_t possible_crtcs; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /** 15262306a36Sopenharmony_ci * @possible_clones: Bitmask of potential sibling encoders for cloning, 15362306a36Sopenharmony_ci * using drm_encoder_index() as the index into the bitfield. The driver 15462306a36Sopenharmony_ci * must set the bits for all &drm_encoder objects which can clone a 15562306a36Sopenharmony_ci * &drm_crtc together with this encoder before calling 15662306a36Sopenharmony_ci * drm_dev_register(). Drivers should set the bit representing the 15762306a36Sopenharmony_ci * encoder itself, too. Cloning bits should be set such that when two 15862306a36Sopenharmony_ci * encoders can be used in a cloned configuration, they both should have 15962306a36Sopenharmony_ci * each another bits set. 16062306a36Sopenharmony_ci * 16162306a36Sopenharmony_ci * As an exception to the above rule if the driver doesn't implement 16262306a36Sopenharmony_ci * any cloning it can leave @possible_clones set to 0. The core will 16362306a36Sopenharmony_ci * automagically fix this up by setting the bit for the encoder itself. 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * You will get a WARN if you get this wrong in the driver. 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * Note that since encoder objects can't be hotplugged the assigned indices 16862306a36Sopenharmony_ci * are stable and hence known before registering all objects. 16962306a36Sopenharmony_ci */ 17062306a36Sopenharmony_ci uint32_t possible_clones; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /** 17362306a36Sopenharmony_ci * @crtc: Currently bound CRTC, only really meaningful for non-atomic 17462306a36Sopenharmony_ci * drivers. Atomic drivers should instead check 17562306a36Sopenharmony_ci * &drm_connector_state.crtc. 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_ci struct drm_crtc *crtc; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /** 18062306a36Sopenharmony_ci * @bridge_chain: Bridges attached to this encoder. Drivers shall not 18162306a36Sopenharmony_ci * access this field directly. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci struct list_head bridge_chain; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci const struct drm_encoder_funcs *funcs; 18662306a36Sopenharmony_ci const struct drm_encoder_helper_funcs *helper_private; 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#define obj_to_encoder(x) container_of(x, struct drm_encoder, base) 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci__printf(5, 6) 19262306a36Sopenharmony_ciint drm_encoder_init(struct drm_device *dev, 19362306a36Sopenharmony_ci struct drm_encoder *encoder, 19462306a36Sopenharmony_ci const struct drm_encoder_funcs *funcs, 19562306a36Sopenharmony_ci int encoder_type, const char *name, ...); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci__printf(5, 6) 19862306a36Sopenharmony_ciint drmm_encoder_init(struct drm_device *dev, 19962306a36Sopenharmony_ci struct drm_encoder *encoder, 20062306a36Sopenharmony_ci const struct drm_encoder_funcs *funcs, 20162306a36Sopenharmony_ci int encoder_type, const char *name, ...); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci__printf(6, 7) 20462306a36Sopenharmony_civoid *__drmm_encoder_alloc(struct drm_device *dev, 20562306a36Sopenharmony_ci size_t size, size_t offset, 20662306a36Sopenharmony_ci const struct drm_encoder_funcs *funcs, 20762306a36Sopenharmony_ci int encoder_type, 20862306a36Sopenharmony_ci const char *name, ...); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/** 21162306a36Sopenharmony_ci * drmm_encoder_alloc - Allocate and initialize an encoder 21262306a36Sopenharmony_ci * @dev: drm device 21362306a36Sopenharmony_ci * @type: the type of the struct which contains struct &drm_encoder 21462306a36Sopenharmony_ci * @member: the name of the &drm_encoder within @type 21562306a36Sopenharmony_ci * @funcs: callbacks for this encoder (optional) 21662306a36Sopenharmony_ci * @encoder_type: user visible type of the encoder 21762306a36Sopenharmony_ci * @name: printf style format string for the encoder name, or NULL for default name 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * Allocates and initializes an encoder. Encoder should be subclassed as part of 22062306a36Sopenharmony_ci * driver encoder objects. Cleanup is automatically handled through registering 22162306a36Sopenharmony_ci * drm_encoder_cleanup() with drmm_add_action(). 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * The @drm_encoder_funcs.destroy hook must be NULL. 22462306a36Sopenharmony_ci * 22562306a36Sopenharmony_ci * Returns: 22662306a36Sopenharmony_ci * Pointer to new encoder, or ERR_PTR on failure. 22762306a36Sopenharmony_ci */ 22862306a36Sopenharmony_ci#define drmm_encoder_alloc(dev, type, member, funcs, encoder_type, name, ...) \ 22962306a36Sopenharmony_ci ((type *)__drmm_encoder_alloc(dev, sizeof(type), \ 23062306a36Sopenharmony_ci offsetof(type, member), funcs, \ 23162306a36Sopenharmony_ci encoder_type, name, ##__VA_ARGS__)) 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/** 23462306a36Sopenharmony_ci * drmm_plain_encoder_alloc - Allocate and initialize an encoder 23562306a36Sopenharmony_ci * @dev: drm device 23662306a36Sopenharmony_ci * @funcs: callbacks for this encoder (optional) 23762306a36Sopenharmony_ci * @encoder_type: user visible type of the encoder 23862306a36Sopenharmony_ci * @name: printf style format string for the encoder name, or NULL for default name 23962306a36Sopenharmony_ci * 24062306a36Sopenharmony_ci * This is a simplified version of drmm_encoder_alloc(), which only allocates 24162306a36Sopenharmony_ci * and returns a struct drm_encoder instance, with no subclassing. 24262306a36Sopenharmony_ci * 24362306a36Sopenharmony_ci * Returns: 24462306a36Sopenharmony_ci * Pointer to the new drm_encoder struct, or ERR_PTR on failure. 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ci#define drmm_plain_encoder_alloc(dev, funcs, encoder_type, name, ...) \ 24762306a36Sopenharmony_ci ((struct drm_encoder *) \ 24862306a36Sopenharmony_ci __drmm_encoder_alloc(dev, sizeof(struct drm_encoder), \ 24962306a36Sopenharmony_ci 0, funcs, encoder_type, name, ##__VA_ARGS__)) 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci/** 25262306a36Sopenharmony_ci * drm_encoder_index - find the index of a registered encoder 25362306a36Sopenharmony_ci * @encoder: encoder to find index for 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * Given a registered encoder, return the index of that encoder within a DRM 25662306a36Sopenharmony_ci * device's list of encoders. 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_cistatic inline unsigned int drm_encoder_index(const struct drm_encoder *encoder) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci return encoder->index; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/** 26462306a36Sopenharmony_ci * drm_encoder_mask - find the mask of a registered encoder 26562306a36Sopenharmony_ci * @encoder: encoder to find mask for 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * Given a registered encoder, return the mask bit of that encoder for an 26862306a36Sopenharmony_ci * encoder's possible_clones field. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_cistatic inline u32 drm_encoder_mask(const struct drm_encoder *encoder) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci return 1 << drm_encoder_index(encoder); 27362306a36Sopenharmony_ci} 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci/** 27662306a36Sopenharmony_ci * drm_encoder_crtc_ok - can a given crtc drive a given encoder? 27762306a36Sopenharmony_ci * @encoder: encoder to test 27862306a36Sopenharmony_ci * @crtc: crtc to test 27962306a36Sopenharmony_ci * 28062306a36Sopenharmony_ci * Returns false if @encoder can't be driven by @crtc, true otherwise. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_cistatic inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder, 28362306a36Sopenharmony_ci struct drm_crtc *crtc) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci return !!(encoder->possible_crtcs & drm_crtc_mask(crtc)); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/** 28962306a36Sopenharmony_ci * drm_encoder_find - find a &drm_encoder 29062306a36Sopenharmony_ci * @dev: DRM device 29162306a36Sopenharmony_ci * @file_priv: drm file to check for lease against. 29262306a36Sopenharmony_ci * @id: encoder id 29362306a36Sopenharmony_ci * 29462306a36Sopenharmony_ci * Returns the encoder with @id, NULL if it doesn't exist. Simple wrapper around 29562306a36Sopenharmony_ci * drm_mode_object_find(). 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_cistatic inline struct drm_encoder *drm_encoder_find(struct drm_device *dev, 29862306a36Sopenharmony_ci struct drm_file *file_priv, 29962306a36Sopenharmony_ci uint32_t id) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci struct drm_mode_object *mo; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_ENCODER); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return mo ? obj_to_encoder(mo) : NULL; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_civoid drm_encoder_cleanup(struct drm_encoder *encoder); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci/** 31162306a36Sopenharmony_ci * drm_for_each_encoder_mask - iterate over encoders specified by bitmask 31262306a36Sopenharmony_ci * @encoder: the loop cursor 31362306a36Sopenharmony_ci * @dev: the DRM device 31462306a36Sopenharmony_ci * @encoder_mask: bitmask of encoder indices 31562306a36Sopenharmony_ci * 31662306a36Sopenharmony_ci * Iterate over all encoders specified by bitmask. 31762306a36Sopenharmony_ci */ 31862306a36Sopenharmony_ci#define drm_for_each_encoder_mask(encoder, dev, encoder_mask) \ 31962306a36Sopenharmony_ci list_for_each_entry((encoder), &(dev)->mode_config.encoder_list, head) \ 32062306a36Sopenharmony_ci for_each_if ((encoder_mask) & drm_encoder_mask(encoder)) 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/** 32362306a36Sopenharmony_ci * drm_for_each_encoder - iterate over all encoders 32462306a36Sopenharmony_ci * @encoder: the loop cursor 32562306a36Sopenharmony_ci * @dev: the DRM device 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * Iterate over all encoders of @dev. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci#define drm_for_each_encoder(encoder, dev) \ 33062306a36Sopenharmony_ci list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head) 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci#endif 333