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_FRAMEBUFFER_H__
2462306a36Sopenharmony_ci#define __DRM_FRAMEBUFFER_H__
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <linux/ctype.h>
2762306a36Sopenharmony_ci#include <linux/list.h>
2862306a36Sopenharmony_ci#include <linux/sched.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <drm/drm_fourcc.h>
3162306a36Sopenharmony_ci#include <drm/drm_mode_object.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistruct drm_clip_rect;
3462306a36Sopenharmony_cistruct drm_device;
3562306a36Sopenharmony_cistruct drm_file;
3662306a36Sopenharmony_cistruct drm_framebuffer;
3762306a36Sopenharmony_cistruct drm_gem_object;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/**
4062306a36Sopenharmony_ci * struct drm_framebuffer_funcs - framebuffer hooks
4162306a36Sopenharmony_ci */
4262306a36Sopenharmony_cistruct drm_framebuffer_funcs {
4362306a36Sopenharmony_ci	/**
4462306a36Sopenharmony_ci	 * @destroy:
4562306a36Sopenharmony_ci	 *
4662306a36Sopenharmony_ci	 * Clean up framebuffer resources, specifically also unreference the
4762306a36Sopenharmony_ci	 * backing storage. The core guarantees to call this function for every
4862306a36Sopenharmony_ci	 * framebuffer successfully created by calling
4962306a36Sopenharmony_ci	 * &drm_mode_config_funcs.fb_create. Drivers must also call
5062306a36Sopenharmony_ci	 * drm_framebuffer_cleanup() to release DRM core resources for this
5162306a36Sopenharmony_ci	 * framebuffer.
5262306a36Sopenharmony_ci	 */
5362306a36Sopenharmony_ci	void (*destroy)(struct drm_framebuffer *framebuffer);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	/**
5662306a36Sopenharmony_ci	 * @create_handle:
5762306a36Sopenharmony_ci	 *
5862306a36Sopenharmony_ci	 * Create a buffer handle in the driver-specific buffer manager (either
5962306a36Sopenharmony_ci	 * GEM or TTM) valid for the passed-in &struct drm_file. This is used by
6062306a36Sopenharmony_ci	 * the core to implement the GETFB IOCTL, which returns (for
6162306a36Sopenharmony_ci	 * sufficiently priviledged user) also a native buffer handle. This can
6262306a36Sopenharmony_ci	 * be used for seamless transitions between modesetting clients by
6362306a36Sopenharmony_ci	 * copying the current screen contents to a private buffer and blending
6462306a36Sopenharmony_ci	 * between that and the new contents.
6562306a36Sopenharmony_ci	 *
6662306a36Sopenharmony_ci	 * GEM based drivers should call drm_gem_handle_create() to create the
6762306a36Sopenharmony_ci	 * handle.
6862306a36Sopenharmony_ci	 *
6962306a36Sopenharmony_ci	 * RETURNS:
7062306a36Sopenharmony_ci	 *
7162306a36Sopenharmony_ci	 * 0 on success or a negative error code on failure.
7262306a36Sopenharmony_ci	 */
7362306a36Sopenharmony_ci	int (*create_handle)(struct drm_framebuffer *fb,
7462306a36Sopenharmony_ci			     struct drm_file *file_priv,
7562306a36Sopenharmony_ci			     unsigned int *handle);
7662306a36Sopenharmony_ci	/**
7762306a36Sopenharmony_ci	 * @dirty:
7862306a36Sopenharmony_ci	 *
7962306a36Sopenharmony_ci	 * Optional callback for the dirty fb IOCTL.
8062306a36Sopenharmony_ci	 *
8162306a36Sopenharmony_ci	 * Userspace can notify the driver via this callback that an area of the
8262306a36Sopenharmony_ci	 * framebuffer has changed and should be flushed to the display
8362306a36Sopenharmony_ci	 * hardware. This can also be used internally, e.g. by the fbdev
8462306a36Sopenharmony_ci	 * emulation, though that's not the case currently.
8562306a36Sopenharmony_ci	 *
8662306a36Sopenharmony_ci	 * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
8762306a36Sopenharmony_ci	 * for more information as all the semantics and arguments have a one to
8862306a36Sopenharmony_ci	 * one mapping on this function.
8962306a36Sopenharmony_ci	 *
9062306a36Sopenharmony_ci	 * Atomic drivers should use drm_atomic_helper_dirtyfb() to implement
9162306a36Sopenharmony_ci	 * this hook.
9262306a36Sopenharmony_ci	 *
9362306a36Sopenharmony_ci	 * RETURNS:
9462306a36Sopenharmony_ci	 *
9562306a36Sopenharmony_ci	 * 0 on success or a negative error code on failure.
9662306a36Sopenharmony_ci	 */
9762306a36Sopenharmony_ci	int (*dirty)(struct drm_framebuffer *framebuffer,
9862306a36Sopenharmony_ci		     struct drm_file *file_priv, unsigned flags,
9962306a36Sopenharmony_ci		     unsigned color, struct drm_clip_rect *clips,
10062306a36Sopenharmony_ci		     unsigned num_clips);
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/**
10462306a36Sopenharmony_ci * struct drm_framebuffer - frame buffer object
10562306a36Sopenharmony_ci *
10662306a36Sopenharmony_ci * Note that the fb is refcounted for the benefit of driver internals,
10762306a36Sopenharmony_ci * for example some hw, disabling a CRTC/plane is asynchronous, and
10862306a36Sopenharmony_ci * scanout does not actually complete until the next vblank.  So some
10962306a36Sopenharmony_ci * cleanup (like releasing the reference(s) on the backing GEM bo(s))
11062306a36Sopenharmony_ci * should be deferred.  In cases like this, the driver would like to
11162306a36Sopenharmony_ci * hold a ref to the fb even though it has already been removed from
11262306a36Sopenharmony_ci * userspace perspective. See drm_framebuffer_get() and
11362306a36Sopenharmony_ci * drm_framebuffer_put().
11462306a36Sopenharmony_ci *
11562306a36Sopenharmony_ci * The refcount is stored inside the mode object @base.
11662306a36Sopenharmony_ci */
11762306a36Sopenharmony_cistruct drm_framebuffer {
11862306a36Sopenharmony_ci	/**
11962306a36Sopenharmony_ci	 * @dev: DRM device this framebuffer belongs to
12062306a36Sopenharmony_ci	 */
12162306a36Sopenharmony_ci	struct drm_device *dev;
12262306a36Sopenharmony_ci	/**
12362306a36Sopenharmony_ci	 * @head: Place on the &drm_mode_config.fb_list, access protected by
12462306a36Sopenharmony_ci	 * &drm_mode_config.fb_lock.
12562306a36Sopenharmony_ci	 */
12662306a36Sopenharmony_ci	struct list_head head;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/**
12962306a36Sopenharmony_ci	 * @base: base modeset object structure, contains the reference count.
13062306a36Sopenharmony_ci	 */
13162306a36Sopenharmony_ci	struct drm_mode_object base;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	/**
13462306a36Sopenharmony_ci	 * @comm: Name of the process allocating the fb, used for fb dumping.
13562306a36Sopenharmony_ci	 */
13662306a36Sopenharmony_ci	char comm[TASK_COMM_LEN];
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	/**
13962306a36Sopenharmony_ci	 * @format: framebuffer format information
14062306a36Sopenharmony_ci	 */
14162306a36Sopenharmony_ci	const struct drm_format_info *format;
14262306a36Sopenharmony_ci	/**
14362306a36Sopenharmony_ci	 * @funcs: framebuffer vfunc table
14462306a36Sopenharmony_ci	 */
14562306a36Sopenharmony_ci	const struct drm_framebuffer_funcs *funcs;
14662306a36Sopenharmony_ci	/**
14762306a36Sopenharmony_ci	 * @pitches: Line stride per buffer. For userspace created object this
14862306a36Sopenharmony_ci	 * is copied from drm_mode_fb_cmd2.
14962306a36Sopenharmony_ci	 */
15062306a36Sopenharmony_ci	unsigned int pitches[DRM_FORMAT_MAX_PLANES];
15162306a36Sopenharmony_ci	/**
15262306a36Sopenharmony_ci	 * @offsets: Offset from buffer start to the actual pixel data in bytes,
15362306a36Sopenharmony_ci	 * per buffer. For userspace created object this is copied from
15462306a36Sopenharmony_ci	 * drm_mode_fb_cmd2.
15562306a36Sopenharmony_ci	 *
15662306a36Sopenharmony_ci	 * Note that this is a linear offset and does not take into account
15762306a36Sopenharmony_ci	 * tiling or buffer layout per @modifier. It is meant to be used when
15862306a36Sopenharmony_ci	 * the actual pixel data for this framebuffer plane starts at an offset,
15962306a36Sopenharmony_ci	 * e.g. when multiple planes are allocated within the same backing
16062306a36Sopenharmony_ci	 * storage buffer object. For tiled layouts this generally means its
16162306a36Sopenharmony_ci	 * @offsets must at least be tile-size aligned, but hardware often has
16262306a36Sopenharmony_ci	 * stricter requirements.
16362306a36Sopenharmony_ci	 *
16462306a36Sopenharmony_ci	 * This should not be used to specifiy x/y pixel offsets into the buffer
16562306a36Sopenharmony_ci	 * data (even for linear buffers). Specifying an x/y pixel offset is
16662306a36Sopenharmony_ci	 * instead done through the source rectangle in &struct drm_plane_state.
16762306a36Sopenharmony_ci	 */
16862306a36Sopenharmony_ci	unsigned int offsets[DRM_FORMAT_MAX_PLANES];
16962306a36Sopenharmony_ci	/**
17062306a36Sopenharmony_ci	 * @modifier: Data layout modifier. This is used to describe
17162306a36Sopenharmony_ci	 * tiling, or also special layouts (like compression) of auxiliary
17262306a36Sopenharmony_ci	 * buffers. For userspace created object this is copied from
17362306a36Sopenharmony_ci	 * drm_mode_fb_cmd2.
17462306a36Sopenharmony_ci	 */
17562306a36Sopenharmony_ci	uint64_t modifier;
17662306a36Sopenharmony_ci	/**
17762306a36Sopenharmony_ci	 * @width: Logical width of the visible area of the framebuffer, in
17862306a36Sopenharmony_ci	 * pixels.
17962306a36Sopenharmony_ci	 */
18062306a36Sopenharmony_ci	unsigned int width;
18162306a36Sopenharmony_ci	/**
18262306a36Sopenharmony_ci	 * @height: Logical height of the visible area of the framebuffer, in
18362306a36Sopenharmony_ci	 * pixels.
18462306a36Sopenharmony_ci	 */
18562306a36Sopenharmony_ci	unsigned int height;
18662306a36Sopenharmony_ci	/**
18762306a36Sopenharmony_ci	 * @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or
18862306a36Sopenharmony_ci	 * DRM_MODE_FB_MODIFIERS.
18962306a36Sopenharmony_ci	 */
19062306a36Sopenharmony_ci	int flags;
19162306a36Sopenharmony_ci	/**
19262306a36Sopenharmony_ci	 * @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor
19362306a36Sopenharmony_ci	 * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
19462306a36Sopenharmony_ci	 * universal plane.
19562306a36Sopenharmony_ci	 */
19662306a36Sopenharmony_ci	int hot_x;
19762306a36Sopenharmony_ci	/**
19862306a36Sopenharmony_ci	 * @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor
19962306a36Sopenharmony_ci	 * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
20062306a36Sopenharmony_ci	 * universal plane.
20162306a36Sopenharmony_ci	 */
20262306a36Sopenharmony_ci	int hot_y;
20362306a36Sopenharmony_ci	/**
20462306a36Sopenharmony_ci	 * @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock.
20562306a36Sopenharmony_ci	 */
20662306a36Sopenharmony_ci	struct list_head filp_head;
20762306a36Sopenharmony_ci	/**
20862306a36Sopenharmony_ci	 * @obj: GEM objects backing the framebuffer, one per plane (optional).
20962306a36Sopenharmony_ci	 *
21062306a36Sopenharmony_ci	 * This is used by the GEM framebuffer helpers, see e.g.
21162306a36Sopenharmony_ci	 * drm_gem_fb_create().
21262306a36Sopenharmony_ci	 */
21362306a36Sopenharmony_ci	struct drm_gem_object *obj[DRM_FORMAT_MAX_PLANES];
21462306a36Sopenharmony_ci};
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ciint drm_framebuffer_init(struct drm_device *dev,
21962306a36Sopenharmony_ci			 struct drm_framebuffer *fb,
22062306a36Sopenharmony_ci			 const struct drm_framebuffer_funcs *funcs);
22162306a36Sopenharmony_cistruct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
22262306a36Sopenharmony_ci					       struct drm_file *file_priv,
22362306a36Sopenharmony_ci					       uint32_t id);
22462306a36Sopenharmony_civoid drm_framebuffer_remove(struct drm_framebuffer *fb);
22562306a36Sopenharmony_civoid drm_framebuffer_cleanup(struct drm_framebuffer *fb);
22662306a36Sopenharmony_civoid drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci/**
22962306a36Sopenharmony_ci * drm_framebuffer_get - acquire a framebuffer reference
23062306a36Sopenharmony_ci * @fb: DRM framebuffer
23162306a36Sopenharmony_ci *
23262306a36Sopenharmony_ci * This function increments the framebuffer's reference count.
23362306a36Sopenharmony_ci */
23462306a36Sopenharmony_cistatic inline void drm_framebuffer_get(struct drm_framebuffer *fb)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	drm_mode_object_get(&fb->base);
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci/**
24062306a36Sopenharmony_ci * drm_framebuffer_put - release a framebuffer reference
24162306a36Sopenharmony_ci * @fb: DRM framebuffer
24262306a36Sopenharmony_ci *
24362306a36Sopenharmony_ci * This function decrements the framebuffer's reference count and frees the
24462306a36Sopenharmony_ci * framebuffer if the reference count drops to zero.
24562306a36Sopenharmony_ci */
24662306a36Sopenharmony_cistatic inline void drm_framebuffer_put(struct drm_framebuffer *fb)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	drm_mode_object_put(&fb->base);
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci/**
25262306a36Sopenharmony_ci * drm_framebuffer_read_refcount - read the framebuffer reference count.
25362306a36Sopenharmony_ci * @fb: framebuffer
25462306a36Sopenharmony_ci *
25562306a36Sopenharmony_ci * This functions returns the framebuffer's reference count.
25662306a36Sopenharmony_ci */
25762306a36Sopenharmony_cistatic inline uint32_t drm_framebuffer_read_refcount(const struct drm_framebuffer *fb)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	return kref_read(&fb->base.refcount);
26062306a36Sopenharmony_ci}
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci/**
26362306a36Sopenharmony_ci * drm_framebuffer_assign - store a reference to the fb
26462306a36Sopenharmony_ci * @p: location to store framebuffer
26562306a36Sopenharmony_ci * @fb: new framebuffer (maybe NULL)
26662306a36Sopenharmony_ci *
26762306a36Sopenharmony_ci * This functions sets the location to store a reference to the framebuffer,
26862306a36Sopenharmony_ci * unreferencing the framebuffer that was previously stored in that location.
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_cistatic inline void drm_framebuffer_assign(struct drm_framebuffer **p,
27162306a36Sopenharmony_ci					  struct drm_framebuffer *fb)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	if (fb)
27462306a36Sopenharmony_ci		drm_framebuffer_get(fb);
27562306a36Sopenharmony_ci	if (*p)
27662306a36Sopenharmony_ci		drm_framebuffer_put(*p);
27762306a36Sopenharmony_ci	*p = fb;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci/*
28162306a36Sopenharmony_ci * drm_for_each_fb - iterate over all framebuffers
28262306a36Sopenharmony_ci * @fb: the loop cursor
28362306a36Sopenharmony_ci * @dev: the DRM device
28462306a36Sopenharmony_ci *
28562306a36Sopenharmony_ci * Iterate over all framebuffers of @dev. User must hold
28662306a36Sopenharmony_ci * &drm_mode_config.fb_lock.
28762306a36Sopenharmony_ci */
28862306a36Sopenharmony_ci#define drm_for_each_fb(fb, dev) \
28962306a36Sopenharmony_ci	for (WARN_ON(!mutex_is_locked(&(dev)->mode_config.fb_lock)),		\
29062306a36Sopenharmony_ci	     fb = list_first_entry(&(dev)->mode_config.fb_list,	\
29162306a36Sopenharmony_ci					  struct drm_framebuffer, head);	\
29262306a36Sopenharmony_ci	     &fb->head != (&(dev)->mode_config.fb_list);			\
29362306a36Sopenharmony_ci	     fb = list_next_entry(fb, head))
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciint drm_framebuffer_plane_width(int width,
29662306a36Sopenharmony_ci				const struct drm_framebuffer *fb, int plane);
29762306a36Sopenharmony_ciint drm_framebuffer_plane_height(int height,
29862306a36Sopenharmony_ci				 const struct drm_framebuffer *fb, int plane);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci/**
30162306a36Sopenharmony_ci * struct drm_afbc_framebuffer - a special afbc frame buffer object
30262306a36Sopenharmony_ci *
30362306a36Sopenharmony_ci * A derived class of struct drm_framebuffer, dedicated for afbc use cases.
30462306a36Sopenharmony_ci */
30562306a36Sopenharmony_cistruct drm_afbc_framebuffer {
30662306a36Sopenharmony_ci	/**
30762306a36Sopenharmony_ci	 * @base: base framebuffer structure.
30862306a36Sopenharmony_ci	 */
30962306a36Sopenharmony_ci	struct drm_framebuffer base;
31062306a36Sopenharmony_ci	/**
31162306a36Sopenharmony_ci	 * @block_width: width of a single afbc block
31262306a36Sopenharmony_ci	 */
31362306a36Sopenharmony_ci	u32 block_width;
31462306a36Sopenharmony_ci	/**
31562306a36Sopenharmony_ci	 * @block_height: height of a single afbc block
31662306a36Sopenharmony_ci	 */
31762306a36Sopenharmony_ci	u32 block_height;
31862306a36Sopenharmony_ci	/**
31962306a36Sopenharmony_ci	 * @aligned_width: aligned frame buffer width
32062306a36Sopenharmony_ci	 */
32162306a36Sopenharmony_ci	u32 aligned_width;
32262306a36Sopenharmony_ci	/**
32362306a36Sopenharmony_ci	 * @aligned_height: aligned frame buffer height
32462306a36Sopenharmony_ci	 */
32562306a36Sopenharmony_ci	u32 aligned_height;
32662306a36Sopenharmony_ci	/**
32762306a36Sopenharmony_ci	 * @offset: offset of the first afbc header
32862306a36Sopenharmony_ci	 */
32962306a36Sopenharmony_ci	u32 offset;
33062306a36Sopenharmony_ci	/**
33162306a36Sopenharmony_ci	 * @afbc_size: minimum size of afbc buffer
33262306a36Sopenharmony_ci	 */
33362306a36Sopenharmony_ci	u32 afbc_size;
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci#define fb_to_afbc_fb(x) container_of(x, struct drm_afbc_framebuffer, base)
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci#endif
339