Skip to content

Commit 017da39

Browse files
committed
Merge tag 'mediatek-drm-next-6.9' of https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux into drm-next
Mediatek DRM Next for Linux 6.9 1. Add display driver for MT8188 VDOSYS1 2. DSI driver cleanups 3. Filter modes according to hardware capability 4. Fix a null pointer crash in mtk_drm_crtc_finish_page_flip Signed-off-by: Dave Airlie <airlied@redhat.com> From: Chun-Kuang Hu <chunkuang.hu@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20240229162143.28957-1-chunkuang.hu@kernel.org
2 parents 1752f13 + c958e86 commit 017da39

File tree

8 files changed

+278
-190
lines changed

8 files changed

+278
-190
lines changed

drivers/gpu/drm/mediatek/mtk_disp_drv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ void mtk_merge_advance_config(struct device *dev, unsigned int l_w, unsigned int
7373
struct cmdq_pkt *cmdq_pkt);
7474
void mtk_merge_start_cmdq(struct device *dev, struct cmdq_pkt *cmdq_pkt);
7575
void mtk_merge_stop_cmdq(struct device *dev, struct cmdq_pkt *cmdq_pkt);
76+
enum drm_mode_status mtk_merge_mode_valid(struct device *dev,
77+
const struct drm_display_mode *mode);
7678

7779
void mtk_ovl_bgclr_in_on(struct device *dev);
7880
void mtk_ovl_bgclr_in_off(struct device *dev);
@@ -131,6 +133,8 @@ unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev);
131133
struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev);
132134
const u32 *mtk_ovl_adaptor_get_formats(struct device *dev);
133135
size_t mtk_ovl_adaptor_get_num_formats(struct device *dev);
136+
enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
137+
const struct drm_display_mode *mode);
134138

135139
void mtk_rdma_bypass_shadow(struct device *dev);
136140
int mtk_rdma_clk_enable(struct device *dev);

drivers/gpu/drm/mediatek/mtk_disp_merge.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,71 @@ void mtk_merge_clk_disable(struct device *dev)
222222
clk_disable_unprepare(priv->clk);
223223
}
224224

225+
enum drm_mode_status mtk_merge_mode_valid(struct device *dev,
226+
const struct drm_display_mode *mode)
227+
{
228+
struct mtk_disp_merge *priv = dev_get_drvdata(dev);
229+
unsigned long rate;
230+
231+
rate = clk_get_rate(priv->clk);
232+
233+
/* Convert to KHz and round the number */
234+
rate = (rate + 500) / 1000;
235+
236+
if (rate && mode->clock > rate) {
237+
dev_dbg(dev, "invalid clock: %d (>%lu)\n", mode->clock, rate);
238+
return MODE_CLOCK_HIGH;
239+
}
240+
241+
/*
242+
* Measure the bandwidth requirement of hardware prefetch (per frame)
243+
*
244+
* let N = prefetch buffer size in lines
245+
* (ex. N=3, then prefetch buffer size = 3 lines)
246+
*
247+
* prefetch size = htotal * N (pixels)
248+
* time per line = 1 / fps / vtotal (seconds)
249+
* duration = vbp * time per line
250+
* = vbp / fps / vtotal
251+
*
252+
* data rate = prefetch size / duration
253+
* = htotal * N / (vbp / fps / vtotal)
254+
* = htotal * vtotal * fps * N / vbp
255+
* = clk * N / vbp (pixels per second)
256+
*
257+
* Say 4K60 (CEA-861) is the maximum mode supported by the SoC
258+
* data rate = 594000K * N / 72 = 8250 (standard)
259+
* (remove K * N due to the same unit)
260+
*
261+
* For 2560x1440@144 (clk=583600K, vbp=17):
262+
* data rate = 583600 / 17 ~= 34329 > 8250 (NG)
263+
*
264+
* For 2560x1440@120 (clk=497760K, vbp=77):
265+
* data rate = 497760 / 77 ~= 6464 < 8250 (OK)
266+
*
267+
* A non-standard 4K60 timing (clk=521280K, vbp=54)
268+
* data rate = 521280 / 54 ~= 9653 > 8250 (NG)
269+
*
270+
* Bandwidth requirement of hardware prefetch increases significantly
271+
* when the VBP decreases (more than 4x in this example).
272+
*
273+
* The proposed formula is only one way to estimate whether our SoC
274+
* supports the mode setting. The basic idea behind it is just to check
275+
* if the data rate requirement is too high (directly proportional to
276+
* pixel clock, inversely proportional to vbp). Please adjust the
277+
* function if it doesn't fit your situation in the future.
278+
*/
279+
rate = mode->clock / (mode->vtotal - mode->vsync_end);
280+
281+
if (rate > 8250) {
282+
dev_dbg(dev, "invalid rate: %lu (>8250): " DRM_MODE_FMT "\n",
283+
rate, DRM_MODE_ARG(mode));
284+
return MODE_BAD;
285+
}
286+
287+
return MODE_OK;
288+
}
289+
225290
static int mtk_disp_merge_bind(struct device *dev, struct device *master,
226291
void *data)
227292
{

drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum mtk_ovl_adaptor_comp_type {
3030
OVL_ADAPTOR_TYPE_ETHDR,
3131
OVL_ADAPTOR_TYPE_MDP_RDMA,
3232
OVL_ADAPTOR_TYPE_MERGE,
33+
OVL_ADAPTOR_TYPE_PADDING,
3334
OVL_ADAPTOR_TYPE_NUM,
3435
};
3536

@@ -47,6 +48,14 @@ enum mtk_ovl_adaptor_comp_id {
4748
OVL_ADAPTOR_MERGE1,
4849
OVL_ADAPTOR_MERGE2,
4950
OVL_ADAPTOR_MERGE3,
51+
OVL_ADAPTOR_PADDING0,
52+
OVL_ADAPTOR_PADDING1,
53+
OVL_ADAPTOR_PADDING2,
54+
OVL_ADAPTOR_PADDING3,
55+
OVL_ADAPTOR_PADDING4,
56+
OVL_ADAPTOR_PADDING5,
57+
OVL_ADAPTOR_PADDING6,
58+
OVL_ADAPTOR_PADDING7,
5059
OVL_ADAPTOR_ID_MAX
5160
};
5261

@@ -67,6 +76,7 @@ static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = {
6776
[OVL_ADAPTOR_TYPE_ETHDR] = "ethdr",
6877
[OVL_ADAPTOR_TYPE_MDP_RDMA] = "vdo1-rdma",
6978
[OVL_ADAPTOR_TYPE_MERGE] = "merge",
79+
[OVL_ADAPTOR_TYPE_PADDING] = "padding",
7080
};
7181

7282
static const struct mtk_ddp_comp_funcs ethdr = {
@@ -79,6 +89,14 @@ static const struct mtk_ddp_comp_funcs ethdr = {
7989
static const struct mtk_ddp_comp_funcs merge = {
8090
.clk_enable = mtk_merge_clk_enable,
8191
.clk_disable = mtk_merge_clk_disable,
92+
.mode_valid = mtk_merge_mode_valid,
93+
};
94+
95+
static const struct mtk_ddp_comp_funcs padding = {
96+
.clk_enable = mtk_padding_clk_enable,
97+
.clk_disable = mtk_padding_clk_disable,
98+
.start = mtk_padding_start,
99+
.stop = mtk_padding_stop,
82100
};
83101

84102
static const struct mtk_ddp_comp_funcs rdma = {
@@ -102,6 +120,14 @@ static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = {
102120
[OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2, &merge },
103121
[OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3, &merge },
104122
[OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4, &merge },
123+
[OVL_ADAPTOR_PADDING0] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING0, 0, &padding },
124+
[OVL_ADAPTOR_PADDING1] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING1, 1, &padding },
125+
[OVL_ADAPTOR_PADDING2] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING2, 2, &padding },
126+
[OVL_ADAPTOR_PADDING3] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING3, 3, &padding },
127+
[OVL_ADAPTOR_PADDING4] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING4, 4, &padding },
128+
[OVL_ADAPTOR_PADDING5] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING5, 5, &padding },
129+
[OVL_ADAPTOR_PADDING6] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING6, 6, &padding },
130+
[OVL_ADAPTOR_PADDING7] = { OVL_ADAPTOR_TYPE_PADDING, DDP_COMPONENT_PADDING7, 7, &padding },
105131
};
106132

107133
void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx,
@@ -317,6 +343,22 @@ void mtk_ovl_adaptor_clk_disable(struct device *dev)
317343
}
318344
}
319345

346+
enum drm_mode_status mtk_ovl_adaptor_mode_valid(struct device *dev,
347+
const struct drm_display_mode *mode)
348+
349+
{
350+
int i;
351+
struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev);
352+
353+
for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) {
354+
dev = ovl_adaptor->ovl_adaptor_comp[i];
355+
if (!dev || !comp_matches[i].funcs->mode_valid)
356+
continue;
357+
return comp_matches[i].funcs->mode_valid(dev, mode);
358+
}
359+
return MODE_OK;
360+
}
361+
320362
unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev)
321363
{
322364
return MTK_OVL_ADAPTOR_LAYER_NUM;
@@ -437,6 +479,7 @@ static int ovl_adaptor_comp_get_id(struct device *dev, struct device_node *node,
437479
}
438480

439481
static const struct of_device_id mtk_ovl_adaptor_comp_dt_ids[] = {
482+
{ .compatible = "mediatek,mt8188-disp-padding", .data = (void *)OVL_ADAPTOR_TYPE_PADDING },
440483
{ .compatible = "mediatek,mt8195-disp-ethdr", .data = (void *)OVL_ADAPTOR_TYPE_ETHDR },
441484
{ .compatible = "mediatek,mt8195-disp-merge", .data = (void *)OVL_ADAPTOR_TYPE_MERGE },
442485
{ .compatible = "mediatek,mt8195-vdo1-rdma", .data = (void *)OVL_ADAPTOR_TYPE_MDP_RDMA },

drivers/gpu/drm/mediatek/mtk_drm_crtc.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,13 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
9595
struct drm_crtc *crtc = &mtk_crtc->base;
9696
unsigned long flags;
9797

98-
spin_lock_irqsave(&crtc->dev->event_lock, flags);
99-
drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
100-
drm_crtc_vblank_put(crtc);
101-
mtk_crtc->event = NULL;
102-
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
98+
if (mtk_crtc->event) {
99+
spin_lock_irqsave(&crtc->dev->event_lock, flags);
100+
drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
101+
drm_crtc_vblank_put(crtc);
102+
mtk_crtc->event = NULL;
103+
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
104+
}
103105
}
104106

105107
static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
@@ -213,6 +215,22 @@ static void mtk_drm_crtc_destroy_state(struct drm_crtc *crtc,
213215
kfree(to_mtk_crtc_state(state));
214216
}
215217

218+
static enum drm_mode_status
219+
mtk_drm_crtc_mode_valid(struct drm_crtc *crtc,
220+
const struct drm_display_mode *mode)
221+
{
222+
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
223+
enum drm_mode_status status = MODE_OK;
224+
int i;
225+
226+
for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
227+
status = mtk_ddp_comp_mode_valid(mtk_crtc->ddp_comp[i], mode);
228+
if (status != MODE_OK)
229+
break;
230+
}
231+
return status;
232+
}
233+
216234
static bool mtk_drm_crtc_mode_fixup(struct drm_crtc *crtc,
217235
const struct drm_display_mode *mode,
218236
struct drm_display_mode *adjusted_mode)
@@ -831,6 +849,7 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
831849
static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = {
832850
.mode_fixup = mtk_drm_crtc_mode_fixup,
833851
.mode_set_nofb = mtk_drm_crtc_mode_set_nofb,
852+
.mode_valid = mtk_drm_crtc_mode_valid,
834853
.atomic_begin = mtk_drm_crtc_atomic_begin,
835854
.atomic_flush = mtk_drm_crtc_atomic_flush,
836855
.atomic_enable = mtk_drm_crtc_atomic_enable,

drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ static const struct mtk_ddp_comp_funcs ddp_ovl_adaptor = {
418418
.remove = mtk_ovl_adaptor_remove_comp,
419419
.get_formats = mtk_ovl_adaptor_get_formats,
420420
.get_num_formats = mtk_ovl_adaptor_get_num_formats,
421+
.mode_valid = mtk_ovl_adaptor_mode_valid,
421422
};
422423

423424
static const char * const mtk_ddp_comp_stem[MTK_DDP_COMP_TYPE_MAX] = {

drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <linux/soc/mediatek/mtk-mmsys.h>
1313
#include <linux/soc/mediatek/mtk-mutex.h>
1414

15+
#include <drm/drm_modes.h>
16+
1517
struct device;
1618
struct device_node;
1719
struct drm_crtc;
@@ -85,6 +87,7 @@ struct mtk_ddp_comp_funcs {
8587
void (*add)(struct device *dev, struct mtk_mutex *mutex);
8688
void (*remove)(struct device *dev, struct mtk_mutex *mutex);
8789
unsigned int (*encoder_index)(struct device *dev);
90+
enum drm_mode_status (*mode_valid)(struct device *dev, const struct drm_display_mode *mode);
8891
};
8992

9093
struct mtk_ddp_comp {
@@ -126,6 +129,15 @@ static inline void mtk_ddp_comp_clk_disable(struct mtk_ddp_comp *comp)
126129
comp->funcs->clk_disable(comp->dev);
127130
}
128131

132+
static inline
133+
enum drm_mode_status mtk_ddp_comp_mode_valid(struct mtk_ddp_comp *comp,
134+
const struct drm_display_mode *mode)
135+
{
136+
if (comp && comp->funcs && comp->funcs->mode_valid)
137+
return comp->funcs->mode_valid(comp->dev, mode);
138+
return MODE_OK;
139+
}
140+
129141
static inline void mtk_ddp_comp_config(struct mtk_ddp_comp *comp,
130142
unsigned int w, unsigned int h,
131143
unsigned int vrefresh, unsigned int bpc,

drivers/gpu/drm/mediatek/mtk_drm_drv.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = {
293293
.main_len = ARRAY_SIZE(mt8188_mtk_ddp_main),
294294
.conn_routes = mt8188_mtk_ddp_main_routes,
295295
.num_conn_routes = ARRAY_SIZE(mt8188_mtk_ddp_main_routes),
296-
.mmsys_dev_num = 1,
296+
.mmsys_dev_num = 2,
297297
};
298298

299299
static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
@@ -334,6 +334,8 @@ static const struct of_device_id mtk_drm_of_ids[] = {
334334
.data = &mt8186_mmsys_driver_data},
335335
{ .compatible = "mediatek,mt8188-vdosys0",
336336
.data = &mt8188_vdosys0_driver_data},
337+
{ .compatible = "mediatek,mt8188-vdosys1",
338+
.data = &mt8195_vdosys1_driver_data},
337339
{ .compatible = "mediatek,mt8192-mmsys",
338340
.data = &mt8192_mmsys_driver_data},
339341
{ .compatible = "mediatek,mt8195-mmsys",

0 commit comments

Comments
 (0)