]>
Commit | Line | Data |
---|---|---|
caab277b | 1 | // SPDX-License-Identifier: GPL-2.0-only |
b961c48b JS |
2 | /* |
3 | * Copyright (C) 2015 Texas Instruments | |
4 | * Author: Jyri Sarha <jsarha@ti.com> | |
b961c48b JS |
5 | */ |
6 | ||
7 | #include <drm/drmP.h> | |
8 | ||
9 | #include <drm/drm_atomic.h> | |
10 | #include <drm/drm_plane_helper.h> | |
11 | #include <drm/drm_atomic_helper.h> | |
12 | #include <uapi/drm/drm_fourcc.h> | |
13 | ||
14 | #include "tilcdc_drv.h" | |
15 | ||
b961c48b JS |
16 | static struct drm_plane_funcs tilcdc_plane_funcs = { |
17 | .update_plane = drm_atomic_helper_update_plane, | |
18 | .disable_plane = drm_atomic_helper_disable_plane, | |
19 | .destroy = drm_plane_cleanup, | |
b961c48b JS |
20 | .reset = drm_atomic_helper_plane_reset, |
21 | .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, | |
22 | .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, | |
23 | }; | |
24 | ||
25 | static int tilcdc_plane_atomic_check(struct drm_plane *plane, | |
26 | struct drm_plane_state *state) | |
27 | { | |
28 | struct drm_crtc_state *crtc_state; | |
29 | struct drm_plane_state *old_state = plane->state; | |
59f11a43 | 30 | unsigned int pitch; |
b961c48b JS |
31 | |
32 | if (!state->crtc) | |
33 | return 0; | |
34 | ||
35 | if (WARN_ON(!state->fb)) | |
36 | return -EINVAL; | |
37 | ||
38 | if (state->crtc_x || state->crtc_y) { | |
39 | dev_err(plane->dev->dev, "%s: crtc position must be zero.", | |
40 | __func__); | |
41 | return -EINVAL; | |
42 | } | |
43 | ||
44 | crtc_state = drm_atomic_get_existing_crtc_state(state->state, | |
45 | state->crtc); | |
46 | /* we should have a crtc state if the plane is attached to a crtc */ | |
47 | if (WARN_ON(!crtc_state)) | |
48 | return 0; | |
49 | ||
50 | if (crtc_state->mode.hdisplay != state->crtc_w || | |
51 | crtc_state->mode.vdisplay != state->crtc_h) { | |
52 | dev_err(plane->dev->dev, | |
53 | "%s: Size must match mode (%dx%d == %dx%d)", __func__, | |
54 | crtc_state->mode.hdisplay, crtc_state->mode.vdisplay, | |
55 | state->crtc_w, state->crtc_h); | |
56 | return -EINVAL; | |
57 | } | |
58 | ||
59f11a43 | 59 | pitch = crtc_state->mode.hdisplay * |
353c8598 | 60 | state->fb->format->cpp[0]; |
59f11a43 | 61 | if (state->fb->pitches[0] != pitch) { |
b961c48b JS |
62 | dev_err(plane->dev->dev, |
63 | "Invalid pitch: fb and crtc widths must be the same"); | |
64 | return -EINVAL; | |
65 | } | |
66 | ||
67 | if (state->fb && old_state->fb && | |
dbd4d576 | 68 | state->fb->format != old_state->fb->format) { |
b961c48b JS |
69 | dev_dbg(plane->dev->dev, |
70 | "%s(): pixel format change requires mode_change\n", | |
71 | __func__); | |
72 | crtc_state->mode_changed = true; | |
73 | } | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
78 | static void tilcdc_plane_atomic_update(struct drm_plane *plane, | |
79 | struct drm_plane_state *old_state) | |
80 | { | |
81 | struct drm_plane_state *state = plane->state; | |
82 | ||
83 | if (!state->crtc) | |
84 | return; | |
85 | ||
86 | if (WARN_ON(!state->fb || !state->crtc->state)) | |
87 | return; | |
88 | ||
e0e344e6 | 89 | tilcdc_crtc_update_fb(state->crtc, |
b961c48b | 90 | state->fb, |
e0e344e6 | 91 | state->crtc->state->event); |
b961c48b JS |
92 | } |
93 | ||
94 | static const struct drm_plane_helper_funcs plane_helper_funcs = { | |
95 | .atomic_check = tilcdc_plane_atomic_check, | |
96 | .atomic_update = tilcdc_plane_atomic_update, | |
97 | }; | |
98 | ||
99 | int tilcdc_plane_init(struct drm_device *dev, | |
100 | struct drm_plane *plane) | |
101 | { | |
bcc5a6f5 | 102 | struct tilcdc_drm_private *priv = dev->dev_private; |
b961c48b JS |
103 | int ret; |
104 | ||
105 | ret = drm_plane_init(dev, plane, 1, | |
106 | &tilcdc_plane_funcs, | |
bcc5a6f5 JS |
107 | priv->pixelformats, |
108 | priv->num_pixelformats, | |
b961c48b JS |
109 | true); |
110 | if (ret) { | |
111 | dev_err(dev->dev, "Failed to initialize plane: %d\n", ret); | |
112 | return ret; | |
113 | } | |
114 | ||
115 | drm_plane_helper_add(plane, &plane_helper_funcs); | |
116 | ||
117 | return 0; | |
118 | } |