Skip to content

Commit 4dd0e97

Browse files
kJugghal-feng
authored andcommitted
drm/vs: Add KMS crtc&plane
add 2 crtcs and 8 planes in vs-drm Signed-off-by: Keith Zhao <keith.zhao@starfivetech.com>
1 parent 4af2e5f commit 4dd0e97

10 files changed

Lines changed: 4685 additions & 1 deletion

File tree

Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2023 VeriSilicon Holdings Co., Ltd.
4+
*
5+
*/
6+
7+
#include <linux/clk.h>
8+
#include <linux/debugfs.h>
9+
#include <linux/media-bus-format.h>
10+
11+
#include <drm/drm_atomic_helper.h>
12+
#include <drm/drm_atomic.h>
13+
#include <drm/drm_crtc.h>
14+
#include <drm/drm_gem_atomic_helper.h>
15+
#include <drm/drm_vblank.h>
16+
#include <drm/vs_drm.h>
17+
18+
#include "vs_crtc.h"
19+
#include "vs_dc.h"
20+
#include "vs_drv.h"
21+
22+
static void vs_crtc_reset(struct drm_crtc *crtc)
23+
{
24+
struct vs_crtc_state *state;
25+
26+
if (crtc->state) {
27+
__drm_atomic_helper_crtc_destroy_state(crtc->state);
28+
29+
state = to_vs_crtc_state(crtc->state);
30+
kfree(state);
31+
crtc->state = NULL;
32+
}
33+
34+
state = kzalloc(sizeof(*state), GFP_KERNEL);
35+
if (!state)
36+
return;
37+
38+
__drm_atomic_helper_crtc_reset(crtc, &state->base);
39+
40+
state->sync_mode = VS_SINGLE_DC;
41+
state->output_fmt = MEDIA_BUS_FMT_RBG888_1X24;
42+
state->encoder_type = DRM_MODE_ENCODER_NONE;
43+
}
44+
45+
static struct drm_crtc_state *
46+
vs_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
47+
{
48+
struct vs_crtc_state *ori_state;
49+
struct vs_crtc_state *state;
50+
51+
if (!crtc->state)
52+
return NULL;
53+
54+
ori_state = to_vs_crtc_state(crtc->state);
55+
state = kzalloc(sizeof(*state), GFP_KERNEL);
56+
if (!state)
57+
return NULL;
58+
59+
__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
60+
61+
state->sync_mode = ori_state->sync_mode;
62+
state->output_fmt = ori_state->output_fmt;
63+
state->encoder_type = ori_state->encoder_type;
64+
state->bg_color = ori_state->bg_color;
65+
state->bpp = ori_state->bpp;
66+
state->sync_enable = ori_state->sync_enable;
67+
state->dither_enable = ori_state->dither_enable;
68+
state->underflow = ori_state->underflow;
69+
70+
return &state->base;
71+
}
72+
73+
static void vs_crtc_atomic_destroy_state(struct drm_crtc *crtc,
74+
struct drm_crtc_state *state)
75+
{
76+
__drm_atomic_helper_crtc_destroy_state(state);
77+
kfree(to_vs_crtc_state(state));
78+
}
79+
80+
static int vs_crtc_atomic_set_property(struct drm_crtc *crtc,
81+
struct drm_crtc_state *state,
82+
struct drm_property *property,
83+
uint64_t val)
84+
{
85+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
86+
struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(state);
87+
88+
if (property == vs_crtc->sync_mode)
89+
vs_crtc_state->sync_mode = val;
90+
else if (property == vs_crtc->mmu_prefetch)
91+
vs_crtc_state->mmu_prefetch = val;
92+
else if (property == vs_crtc->bg_color)
93+
vs_crtc_state->bg_color = val;
94+
else if (property == vs_crtc->panel_sync)
95+
vs_crtc_state->sync_enable = val;
96+
else if (property == vs_crtc->dither)
97+
vs_crtc_state->dither_enable = val;
98+
else
99+
return -EINVAL;
100+
101+
return 0;
102+
}
103+
104+
static int vs_crtc_atomic_get_property(struct drm_crtc *crtc,
105+
const struct drm_crtc_state *state,
106+
struct drm_property *property,
107+
uint64_t *val)
108+
{
109+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
110+
const struct vs_crtc_state *vs_crtc_state =
111+
container_of(state, const struct vs_crtc_state, base);
112+
113+
if (property == vs_crtc->sync_mode)
114+
*val = vs_crtc_state->sync_mode;
115+
else if (property == vs_crtc->mmu_prefetch)
116+
*val = vs_crtc_state->mmu_prefetch;
117+
else if (property == vs_crtc->bg_color)
118+
*val = vs_crtc_state->bg_color;
119+
else if (property == vs_crtc->panel_sync)
120+
*val = vs_crtc_state->sync_enable;
121+
else if (property == vs_crtc->dither)
122+
*val = vs_crtc_state->dither_enable;
123+
else
124+
return -EINVAL;
125+
126+
return 0;
127+
}
128+
129+
static int vs_crtc_late_register(struct drm_crtc *crtc)
130+
{
131+
return 0;
132+
}
133+
134+
static int vs_crtc_enable_vblank(struct drm_crtc *crtc)
135+
{
136+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
137+
138+
vs_dc_enable_vblank(vs_crtc->dev, true);
139+
140+
return 0;
141+
}
142+
143+
static void vs_crtc_disable_vblank(struct drm_crtc *crtc)
144+
{
145+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
146+
147+
vs_dc_enable_vblank(vs_crtc->dev, false);
148+
}
149+
150+
static const struct drm_crtc_funcs vs_crtc_funcs = {
151+
.set_config = drm_atomic_helper_set_config,
152+
.page_flip = drm_atomic_helper_page_flip,
153+
.reset = vs_crtc_reset,
154+
.atomic_duplicate_state = vs_crtc_atomic_duplicate_state,
155+
.atomic_destroy_state = vs_crtc_atomic_destroy_state,
156+
.atomic_set_property = vs_crtc_atomic_set_property,
157+
.atomic_get_property = vs_crtc_atomic_get_property,
158+
.late_register = vs_crtc_late_register,
159+
.enable_vblank = vs_crtc_enable_vblank,
160+
.disable_vblank = vs_crtc_disable_vblank,
161+
};
162+
163+
static u8 cal_pixel_bits(u32 bus_format)
164+
{
165+
u8 bpp;
166+
167+
switch (bus_format) {
168+
case MEDIA_BUS_FMT_RGB565_1X16:
169+
case MEDIA_BUS_FMT_UYVY8_1X16:
170+
bpp = 16;
171+
break;
172+
case MEDIA_BUS_FMT_RGB666_1X18:
173+
case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
174+
bpp = 18;
175+
break;
176+
case MEDIA_BUS_FMT_UYVY10_1X20:
177+
bpp = 20;
178+
break;
179+
case MEDIA_BUS_FMT_BGR888_1X24:
180+
case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
181+
case MEDIA_BUS_FMT_YUV8_1X24:
182+
bpp = 24;
183+
break;
184+
case MEDIA_BUS_FMT_RGB101010_1X30:
185+
case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
186+
case MEDIA_BUS_FMT_YUV10_1X30:
187+
bpp = 30;
188+
break;
189+
default:
190+
bpp = 24;
191+
break;
192+
}
193+
194+
return bpp;
195+
}
196+
197+
static bool vs_crtc_mode_fixup(struct drm_crtc *crtc,
198+
const struct drm_display_mode *mode,
199+
struct drm_display_mode *adjusted_mode)
200+
{
201+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
202+
203+
return vs_dc_mode_fixup(vs_crtc->dev, mode, adjusted_mode);
204+
}
205+
206+
static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
207+
struct drm_atomic_state *state)
208+
{
209+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
210+
struct vs_crtc_state *vs_crtc_state = to_vs_crtc_state(crtc->state);
211+
212+
vs_crtc_state->bpp = cal_pixel_bits(vs_crtc_state->output_fmt);
213+
214+
vs_dc_enable(vs_crtc->dev, crtc);
215+
drm_crtc_vblank_on(crtc);
216+
}
217+
218+
static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
219+
struct drm_atomic_state *state)
220+
{
221+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
222+
223+
drm_crtc_vblank_off(crtc);
224+
225+
vs_dc_disable(vs_crtc->dev, crtc);
226+
227+
if (crtc->state->event && !crtc->state->active) {
228+
spin_lock_irq(&crtc->dev->event_lock);
229+
drm_crtc_send_vblank_event(crtc, crtc->state->event);
230+
spin_unlock_irq(&crtc->dev->event_lock);
231+
232+
crtc->state->event = NULL;
233+
}
234+
}
235+
236+
static void vs_crtc_atomic_begin(struct drm_crtc *crtc,
237+
struct drm_atomic_state *state)
238+
{
239+
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
240+
crtc);
241+
242+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
243+
struct device *dev = vs_crtc->dev;
244+
struct drm_property_blob *blob = crtc->state->gamma_lut;
245+
struct drm_color_lut *lut;
246+
247+
if (crtc_state->color_mgmt_changed) {
248+
if (blob && blob->length) {
249+
lut = blob->data;
250+
vs_dc_set_gamma(dev, crtc, lut,
251+
blob->length / sizeof(*lut));
252+
vs_dc_enable_gamma(dev, crtc, true);
253+
} else {
254+
vs_dc_enable_gamma(dev, crtc, false);
255+
}
256+
}
257+
}
258+
259+
static void vs_crtc_atomic_flush(struct drm_crtc *crtc,
260+
struct drm_atomic_state *state)
261+
{
262+
struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
263+
struct drm_pending_vblank_event *event = crtc->state->event;
264+
265+
vs_dc_commit(vs_crtc->dev);
266+
267+
if (event) {
268+
WARN_ON(drm_crtc_vblank_get(crtc) != 0);
269+
270+
spin_lock_irq(&crtc->dev->event_lock);
271+
drm_crtc_arm_vblank_event(crtc, event);
272+
spin_unlock_irq(&crtc->dev->event_lock);
273+
crtc->state->event = NULL;
274+
}
275+
}
276+
277+
static const struct drm_crtc_helper_funcs vs_crtc_helper_funcs = {
278+
.mode_fixup = vs_crtc_mode_fixup,
279+
.atomic_enable = vs_crtc_atomic_enable,
280+
.atomic_disable = vs_crtc_atomic_disable,
281+
.atomic_begin = vs_crtc_atomic_begin,
282+
.atomic_flush = vs_crtc_atomic_flush,
283+
};
284+
285+
static const struct drm_prop_enum_list vs_sync_mode_enum_list[] = {
286+
{ VS_SINGLE_DC, "single dc mode" },
287+
{ VS_MULTI_DC_PRIMARY, "primary dc for multi dc mode" },
288+
{ VS_MULTI_DC_SECONDARY, "secondary dc for multi dc mode" },
289+
};
290+
291+
struct vs_crtc *vs_crtc_create(struct drm_device *drm_dev,
292+
struct vs_dc_info *info)
293+
{
294+
struct vs_crtc *crtc;
295+
int ret;
296+
297+
if (!info)
298+
return NULL;
299+
300+
crtc = drmm_kzalloc(drm_dev, sizeof(*crtc), GFP_KERNEL);
301+
if (!crtc)
302+
return NULL;
303+
304+
ret = drmm_crtc_init_with_planes(drm_dev, &crtc->base,
305+
NULL, NULL, &vs_crtc_funcs,
306+
info->name ? info->name : NULL);
307+
if (ret)
308+
return NULL;
309+
310+
drm_crtc_helper_add(&crtc->base, &vs_crtc_helper_funcs);
311+
312+
/* Set up the crtc properties */
313+
if (info->pipe_sync) {
314+
crtc->sync_mode = drm_property_create_enum(drm_dev, 0,
315+
"SYNC_MODE",
316+
vs_sync_mode_enum_list,
317+
ARRAY_SIZE(vs_sync_mode_enum_list));
318+
319+
if (!crtc->sync_mode)
320+
return NULL;
321+
322+
drm_object_attach_property(&crtc->base.base,
323+
crtc->sync_mode,
324+
VS_SINGLE_DC);
325+
}
326+
327+
if (info->gamma_size) {
328+
ret = drm_mode_crtc_set_gamma_size(&crtc->base,
329+
info->gamma_size);
330+
if (ret)
331+
return NULL;
332+
333+
drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
334+
info->gamma_size);
335+
}
336+
337+
if (info->background) {
338+
crtc->bg_color = drm_property_create_range(drm_dev, 0,
339+
"BG_COLOR", 0, 0xffffffff);
340+
341+
if (!crtc->bg_color)
342+
return NULL;
343+
344+
drm_object_attach_property(&crtc->base.base, crtc->bg_color, 0);
345+
}
346+
347+
if (info->panel_sync) {
348+
crtc->panel_sync = drm_property_create_bool(drm_dev, 0, "SYNC_ENABLED");
349+
350+
if (!crtc->panel_sync)
351+
return NULL;
352+
353+
drm_object_attach_property(&crtc->base.base, crtc->panel_sync, 0);
354+
}
355+
356+
crtc->dither = drm_property_create_bool(drm_dev, 0, "DITHER_ENABLED");
357+
if (!crtc->dither)
358+
return NULL;
359+
360+
drm_object_attach_property(&crtc->base.base, crtc->dither, 0);
361+
362+
crtc->max_bpc = info->max_bpc;
363+
crtc->color_formats = info->color_formats;
364+
return crtc;
365+
}

0 commit comments

Comments
 (0)