• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff -Naur a/drivers/clk/meson/clk-mux.c b/drivers/clk/meson/clk-mux.c
2--- a/drivers/clk/meson/clk-mux.c	1970-01-01 08:00:00.000000000 +0800
3+++ b/drivers/clk/meson/clk-mux.c	2023-02-23 17:02:04.947750903 +0800
4@@ -0,0 +1,214 @@
5+/*
6+ * drivers/amlogic/clk/clk-mux.c
7+ *
8+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
9+ *
10+ * This program is free software; you can redistribute it and/or modify
11+ * it under the terms of the GNU General Public License as published by
12+ * the Free Software Foundation; either version 2 of the License, or
13+ * (at your option) any later version.
14+ *
15+ * This program is distributed in the hope that it will be useful, but WITHOUT
16+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18+ * more details.
19+ *
20+ */
21+
22+#include <linux/clk.h>
23+#include <linux/clk-provider.h>
24+#include <linux/delay.h>
25+#include <linux/err.h>
26+#include <linux/io.h>
27+#include <linux/module.h>
28+#include <linux/of_address.h>
29+#include <linux/slab.h>
30+#include <linux/string.h>
31+
32+#include "clk-mux.h"
33+
34+
35+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
36+
37+static inline u32 clk_mux_readl(struct clk_mux *mux)
38+{
39+	if (mux->flags & CLK_MUX_BIG_ENDIAN)
40+		return ioread32be(mux->reg);
41+
42+	return readl(mux->reg);
43+}
44+
45+static inline void clk_mux_writel(struct clk_mux *mux, u32 val)
46+{
47+	if (mux->flags & CLK_MUX_BIG_ENDIAN)
48+		iowrite32be(val, mux->reg);
49+	else
50+		writel(val, mux->reg);
51+}
52+
53+
54+static u8 meson_clk_mux_get_parent(struct clk_hw *hw)
55+{
56+	struct clk_mux *mux = to_clk_mux(hw);
57+	int num_parents = clk_hw_get_num_parents(hw);
58+	u32 val;
59+
60+	/*
61+	 * FIXME need a mux-specific flag to determine if val is bitwise or
62+	 * numeric. e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges
63+	 * from 0x1 to 0x7 (index starts at one)
64+	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
65+	 * val = 0x4 really means "bit 2, index starts at bit 0"
66+	 */
67+	val = clk_mux_readl(mux) >> mux->shift;
68+	val &= mux->mask;
69+
70+	if (mux->table) {
71+		int i;
72+
73+		for (i = 0; i < num_parents; i++)
74+			if (mux->table[i] == val)
75+				return i;
76+		return -EINVAL;
77+	}
78+
79+	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
80+		val = ffs(val) - 1;
81+
82+	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
83+		val--;
84+
85+	if (val >= num_parents)
86+		return -EINVAL;
87+
88+	return val;
89+}
90+
91+static int meson_clk_mux_set_parent(struct clk_hw *hw, u8 index)
92+{
93+	struct clk_mux *mux = to_clk_mux(hw);
94+	u32 val;
95+	unsigned long flags = 0;
96+
97+	if (mux->table) {
98+		index = mux->table[index];
99+	} else {
100+		if (mux->flags & CLK_MUX_INDEX_BIT)
101+			index = (1 << ffs(index));
102+
103+		if (mux->flags & CLK_MUX_INDEX_ONE)
104+			index++;
105+	}
106+
107+	if (mux->lock)
108+		spin_lock_irqsave(mux->lock, flags);
109+	else
110+		__acquire(mux->lock);
111+
112+	if (mux->flags & CLK_MUX_HIWORD_MASK) {
113+		val = mux->mask << (mux->shift + 16);
114+	} else {
115+		val = clk_mux_readl(mux);
116+		val &= ~(mux->mask << mux->shift);
117+	}
118+
119+	val |= index << mux->shift;
120+	clk_mux_writel(mux, val);
121+
122+	if (mux->lock)
123+		spin_unlock_irqrestore(mux->lock, flags);
124+	else
125+		__release(mux->lock);
126+
127+	return 0;
128+}
129+
130+static unsigned long meson_clk_mux_recalc_rate(struct clk_hw *hw,
131+					       unsigned long parent_rate)
132+{
133+	struct clk_hw *parent_hw;
134+	u32 index = 0;
135+	unsigned long new_parent_rate;
136+
137+	index = meson_clk_mux_get_parent(hw);
138+
139+	parent_hw = clk_hw_get_parent_by_index(hw, index);
140+	new_parent_rate = clk_hw_get_rate(parent_hw);
141+	if (new_parent_rate != parent_rate)
142+		clk_set_parent(hw->clk, parent_hw->clk);
143+
144+	return new_parent_rate;
145+}
146+
147+int meson_clk_mux_determine_rate(struct clk_hw *hw,
148+			     struct clk_rate_request *req)
149+{
150+	struct clk_hw *parent, *best_parent = NULL;
151+	int i, num_parents, ret;
152+	unsigned long best = 0;
153+	struct clk_rate_request parent_req = *req;
154+	struct clk_mux *mux = to_clk_mux(hw);
155+
156+	num_parents = clk_hw_get_num_parents(hw);
157+
158+	if ((num_parents == 2) && (mux->flags == CLK_PARENT_ALTERNATE)) {
159+		i = meson_clk_mux_get_parent(hw);
160+		i = (i + 1) % 2;
161+
162+		best_parent = clk_hw_get_parent_by_index(hw, i);
163+		best = clk_hw_get_rate(best_parent);
164+		if (best != parent_req.rate) {
165+			ret = clk_set_rate(best_parent->clk, parent_req.rate);
166+			if (ret)
167+				pr_err("Fail! Can not set to %lu, cur rate: %lu\n",
168+				   parent_req.rate, best);
169+			else {
170+				best = clk_hw_get_rate(best_parent);
171+				pr_debug("success set parent %s rate to %lu\n",
172+					clk_hw_get_name(best_parent), best);
173+				if (!(clk_hw_get_flags(hw) &
174+						CLK_SET_RATE_UNGATE)) {
175+					clk_prepare(best_parent->clk);
176+					clk_enable(best_parent->clk);
177+				}
178+			}
179+		}
180+	} else {
181+		for (i = 0; i < num_parents; i++) {
182+			parent = clk_hw_get_parent_by_index(hw, i);
183+			if (!parent)
184+				continue;
185+
186+			if (mux->flags & CLK_SET_RATE_PARENT) {
187+				parent_req = *req;
188+				ret = __clk_determine_rate(parent, &parent_req);
189+				if (ret)
190+					continue;
191+			} else {
192+				parent_req.rate = clk_hw_get_rate(parent);
193+			}
194+		}
195+	}
196+
197+	if (!best_parent)
198+		return -EINVAL;
199+
200+	if (best_parent)
201+		req->best_parent_hw = best_parent;
202+
203+	req->best_parent_rate = best;
204+	req->rate = best;
205+
206+	return 0;
207+}
208+
209+const struct clk_ops meson_clk_mux_ops = {
210+	.get_parent = meson_clk_mux_get_parent,
211+	.set_parent = meson_clk_mux_set_parent,
212+	.determine_rate = meson_clk_mux_determine_rate,
213+	.recalc_rate = meson_clk_mux_recalc_rate,
214+};
215+
216+const struct clk_ops meson_clk_mux_ro_ops = {
217+	.get_parent = meson_clk_mux_get_parent,
218+};
219diff -Naur a/drivers/clk/meson/clk-mux.h b/drivers/clk/meson/clk-mux.h
220--- a/drivers/clk/meson/clk-mux.h	1970-01-01 08:00:00.000000000 +0800
221+++ b/drivers/clk/meson/clk-mux.h	2023-02-23 17:02:04.947750903 +0800
222@@ -0,0 +1,19 @@
223+/* SPDX-License-Identifier: GPL-2.0 */
224+/*
225+ * Copyright (c) 2019 BayLibre, SAS.
226+ * Author: Jerome Brunet <jbrunet@baylibre.com>
227+ */
228+
229+#ifndef __MESON_CLK_MUX_H
230+#define __MESON_CLK_MUX_H
231+
232+#include <linux/clk-provider.h>
233+#include <linux/regmap.h>
234+#include "parm.h"
235+
236+#define CLK_PARENT_ALTERNATE BIT(5)
237+
238+extern const struct clk_ops meson_clk_mux_ops;
239+
240+
241+#endif /* __MESON_CLK_MUX_H */
242diff -Naur a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
243--- a/drivers/clk/meson/clk-pll.c	2022-12-19 17:13:11.809508587 +0800
244+++ b/drivers/clk/meson/clk-pll.c	2023-02-23 17:02:04.947750903 +0800
245@@ -283,6 +283,8 @@
246 		delay--;
247 	} while (delay > 0);
248
249+	pr_warn("%s: pll %s did not lock\n", __func__, clk_hw_get_name(hw));
250+
251 	return -ETIMEDOUT;
252 }
253
254@@ -339,6 +341,9 @@
255 	/* Enable the pll */
256 	meson_parm_write(clk->map, &pll->en, 1);
257
258+	/* Reset delay */
259+	udelay(pll->rst_delay_us);
260+
261 	/* Take the pll out reset */
262 	meson_parm_write(clk->map, &pll->rst, 0);
263
264diff -Naur a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h
265--- a/drivers/clk/meson/clk-pll.h	2022-12-19 17:13:11.809508587 +0800
266+++ b/drivers/clk/meson/clk-pll.h	2023-02-23 17:02:04.947750903 +0800
267@@ -41,6 +41,7 @@
268 	const struct pll_params_table *table;
269 	const struct pll_mult_range *range;
270 	u8 flags;
271+	u32 rst_delay_us;
272 };
273
274 extern const struct clk_ops meson_clk_pll_ro_ops;
275diff -Naur a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
276--- a/drivers/clk/meson/g12a.c	2022-12-19 17:13:11.813508635 +0800
277+++ b/drivers/clk/meson/g12a.c	2023-02-23 17:02:04.951750958 +0800
278@@ -15,6 +15,7 @@
279 #include <linux/of_device.h>
280 #include <linux/platform_device.h>
281 #include <linux/clk.h>
282+#include <linux/of_address.h>
283
284 #include "clk-mpll.h"
285 #include "clk-pll.h"
286@@ -23,8 +24,9 @@
287 #include "vid-pll-div.h"
288 #include "meson-eeclk.h"
289 #include "g12a.h"
290+#include "g12a-vcodec-clk.h"
291
292-static DEFINE_SPINLOCK(meson_clk_lock);
293+/*static*/ DEFINE_SPINLOCK(meson_clk_lock);
294
295 static struct clk_regmap g12a_fixed_pll_dco = {
296 	.data = &(struct meson_clk_pll_data){
297@@ -1602,20 +1604,21 @@
298 };
299
300 static const struct pll_mult_range g12a_gp0_pll_mult_range = {
301-	.min = 125,
302-	.max = 255,
303+	.min = 132, /* Force M to 132 */
304+	.max = 132,
305 };
306
307 /*
308  * Internal gp0 pll emulation configuration parameters
309  */
310 static const struct reg_sequence g12a_gp0_init_regs[] = {
311+	{ .reg = HHI_GP0_PLL_CNTL0,	.def = 0x08000000 },
312 	{ .reg = HHI_GP0_PLL_CNTL1,	.def = 0x00000000 },
313 	{ .reg = HHI_GP0_PLL_CNTL2,	.def = 0x00000000 },
314-	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x48681c00 },
315-	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0x33771290 },
316+	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x6a285c00},
317+	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0x65771290},
318 	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x39272000 },
319-	{ .reg = HHI_GP0_PLL_CNTL6,	.def = 0x56540000 },
320+	{ .reg = HHI_GP0_PLL_CNTL6,	.def = 0x56540000, .delay_us = 10 },
321 };
322
323 static struct clk_regmap g12a_gp0_pll_dco = {
324@@ -1653,6 +1656,7 @@
325 		.range = &g12a_gp0_pll_mult_range,
326 		.init_regs = g12a_gp0_init_regs,
327 		.init_count = ARRAY_SIZE(g12a_gp0_init_regs),
328+		.rst_delay_us = 100,
329 	},
330 	.hw.init = &(struct clk_init_data){
331 		.name = "gp0_pll_dco",
332@@ -3657,6 +3661,86 @@
333 	},
334 };
335
336+/* MIPI DSI Host Clocks */
337+
338+static const struct clk_hw *g12a_mipi_dsi_pxclk_parent_hws[] = {
339+	&g12a_vid_pll.hw,
340+	&g12a_gp0_pll.hw,
341+	&g12a_hifi_pll.hw,
342+	&g12a_mpll1.hw,
343+	&g12a_fclk_div2.hw,
344+	&g12a_fclk_div2p5.hw,
345+	&g12a_fclk_div3.hw,
346+	&g12a_fclk_div7.hw,
347+};
348+
349+static struct clk_regmap g12a_mipi_dsi_pxclk_sel = {
350+	.data = &(struct clk_regmap_mux_data){
351+		.offset = HHI_MIPIDSI_PHY_CLK_CNTL,
352+		.mask = 0x7,
353+		.shift = 12,
354+		.flags = CLK_MUX_ROUND_CLOSEST,
355+	},
356+	.hw.init = &(struct clk_init_data){
357+		.name = "mipi_dsi_pxclk_sel",
358+		.ops = &clk_regmap_mux_ops,
359+		.parent_hws = g12a_mipi_dsi_pxclk_parent_hws,
360+		.num_parents = ARRAY_SIZE(g12a_mipi_dsi_pxclk_parent_hws),
361+		.flags = CLK_SET_RATE_NO_REPARENT,
362+	},
363+};
364+
365+static struct clk_regmap g12a_mipi_dsi_pxclk_div = {
366+	.data = &(struct clk_regmap_div_data){
367+		.offset = HHI_MIPIDSI_PHY_CLK_CNTL,
368+		.shift = 0,
369+		.width = 7,
370+	},
371+	.hw.init = &(struct clk_init_data){
372+		.name = "mipi_dsi_pxclk_div",
373+		.ops = &clk_regmap_divider_ops,
374+		.parent_hws = (const struct clk_hw *[]) {
375+			&g12a_mipi_dsi_pxclk_sel.hw
376+		},
377+		.num_parents = 1,
378+		.flags = CLK_SET_RATE_PARENT,
379+	},
380+};
381+
382+static struct clk_regmap g12a_mipi_dsi_pxclk = {
383+	.data = &(struct clk_regmap_gate_data){
384+		.offset = HHI_MIPIDSI_PHY_CLK_CNTL,
385+		.bit_idx = 8,
386+	},
387+	.hw.init = &(struct clk_init_data) {
388+		.name = "mipi_dsi_pxclk",
389+		.ops = &clk_regmap_gate_ops,
390+		.parent_hws = (const struct clk_hw *[]) {
391+			&g12a_mipi_dsi_pxclk_div.hw
392+		},
393+		.num_parents = 1,
394+		.flags = CLK_SET_RATE_PARENT,
395+	},
396+};
397+
398+/* GPIO 24M */
399+static struct clk_regmap g12a_24m = {
400+	.data = &(struct clk_regmap_gate_data){
401+		.offset = HHI_XTAL_DIVN_CNTL,
402+		.bit_idx = 6,
403+	},
404+	.hw.init = &(struct clk_init_data){
405+		.name = "g12a_24m",
406+		.ops = &clk_regmap_gate_ops,
407+		.parent_names = (const char *[]){ "xtal" },
408+		.parent_data = &(const struct clk_parent_data) {
409+			.fw_name = "xtal",
410+		},
411+		.num_parents = 1,
412+		.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
413+	},
414+};
415+
416 /* HDMI Clocks */
417
418 static const struct clk_parent_data g12a_hdmi_parent_data[] = {
419@@ -4099,6 +4183,96 @@
420 	},
421 };
422
423+static const char * const media_parent_names[] = { "xtal",
424+	"gp0_pll", "hifi_pll", "fclk_div2p5", "fclk_div3", "fclk_div4",
425+	"fclk_div5",  "fclk_div7"};
426+
427+static const char * const media_parent_names_mipi[] = { "xtal",
428+	"gp0_pll", "mpll1", "mpll2", "fclk_div3", "fclk_div4",
429+	"fclk_div5",  "fclk_div7"};
430+
431+static struct clk_mux cts_mipi_isp_clk_mux = {
432+	.reg = (void *)HHI_MIPI_ISP_CLK_CNTL,
433+	.mask = 0x7,
434+	.shift = 9,
435+	.lock = &meson_clk_lock,
436+	.hw.init = &(struct clk_init_data){
437+		.name = "cts_mipi_isp_clk_mux",
438+		.ops = &clk_mux_ops,
439+		.parent_names = media_parent_names,
440+		.num_parents = 8,
441+		.flags = CLK_GET_RATE_NOCACHE,
442+	},
443+};
444+
445+static struct clk_divider cts_mipi_isp_clk_div = {
446+	.reg = (void *)HHI_MIPI_ISP_CLK_CNTL,
447+	.shift = 0,
448+	.width = 7,
449+	.lock = &meson_clk_lock,
450+	.hw.init = &(struct clk_init_data){
451+		.name = "cts_mipi_isp_clk_div",
452+		.ops = &clk_divider_ops,
453+		.parent_names = (const char *[]){ "cts_mipi_isp_clk_mux" },
454+		.num_parents = 1,
455+		.flags = CLK_GET_RATE_NOCACHE,
456+	},
457+};
458+
459+static struct clk_gate cts_mipi_isp_clk_gate = {
460+	.reg = (void *)HHI_MIPI_ISP_CLK_CNTL,
461+	.bit_idx = 8,
462+	.lock = &meson_clk_lock,
463+	.hw.init = &(struct clk_init_data) {
464+		.name = "cts_mipi_isp_clk_gate",
465+		.ops = &clk_gate_ops,
466+		.parent_names = (const char *[]){ "cts_mipi_isp_clk_div" },
467+		.num_parents = 1,
468+		.flags = CLK_GET_RATE_NOCACHE,
469+	},
470+};
471+
472+static struct clk_mux cts_mipi_csi_phy_clk0_mux = {
473+	.reg = (void *)HHI_MIPI_CSI_PHY_CLK_CNTL,
474+	.mask = 0x7,
475+	.shift = 9,
476+	.lock = &meson_clk_lock,
477+	.hw.init = &(struct clk_init_data){
478+		.name = "cts_mipi_csi_phy_clk0_mux",
479+		.ops = &clk_mux_ops,
480+		.parent_names = media_parent_names_mipi,
481+		.num_parents = 8,
482+		.flags = CLK_GET_RATE_NOCACHE,
483+	},
484+};
485+
486+static struct clk_divider cts_mipi_csi_phy_clk0_div = {
487+	.reg = (void *)HHI_MIPI_CSI_PHY_CLK_CNTL,
488+	.shift = 0,
489+	.width = 7,
490+	.lock = &meson_clk_lock,
491+	.hw.init = &(struct clk_init_data){
492+		.name = "cts_mipi_csi_phy_clk0_div",
493+		.ops = &clk_divider_ops,
494+		.parent_names = (const char *[]){ "cts_mipi_csi_phy_clk0_mux" },
495+		.num_parents = 1,
496+		.flags = CLK_GET_RATE_NOCACHE,
497+	},
498+};
499+
500+static struct clk_gate cts_mipi_csi_phy_clk0_gate = {
501+	.reg = (void *)HHI_MIPI_CSI_PHY_CLK_CNTL,
502+	.bit_idx = 8,
503+	.lock = &meson_clk_lock,
504+	.hw.init = &(struct clk_init_data) {
505+		.name = "cts_mipi_csi_phy_clk0_gate",
506+		.ops = &clk_gate_ops,
507+		.parent_names = (const char *[]){ "cts_mipi_csi_phy_clk0_div" },
508+		.num_parents = 1,
509+		.flags = CLK_GET_RATE_NOCACHE,
510+	},
511+};
512+
513 #define MESON_GATE(_name, _reg, _bit) \
514 	MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw)
515
516@@ -4402,6 +4576,9 @@
517 		[CLKID_SPICC1_SCLK_SEL]		= &g12a_spicc1_sclk_sel.hw,
518 		[CLKID_SPICC1_SCLK_DIV]		= &g12a_spicc1_sclk_div.hw,
519 		[CLKID_SPICC1_SCLK]		= &g12a_spicc1_sclk.hw,
520+		[CLKID_MIPI_DSI_PXCLK_SEL]	= &g12a_mipi_dsi_pxclk_sel.hw,
521+		[CLKID_MIPI_DSI_PXCLK_DIV]	= &g12a_mipi_dsi_pxclk_div.hw,
522+		[CLKID_MIPI_DSI_PXCLK]		= &g12a_mipi_dsi_pxclk.hw,
523 		[NR_CLKS]			= NULL,
524 	},
525 	.num = NR_CLKS,
526@@ -4657,6 +4834,16 @@
527 		[CLKID_SPICC1_SCLK_SEL]		= &g12a_spicc1_sclk_sel.hw,
528 		[CLKID_SPICC1_SCLK_DIV]		= &g12a_spicc1_sclk_div.hw,
529 		[CLKID_SPICC1_SCLK]		= &g12a_spicc1_sclk.hw,
530+		[CLKID_NNA_AXI_CLK_SEL]		= &sm1_nna_axi_clk_sel.hw,
531+		[CLKID_NNA_AXI_CLK_DIV]		= &sm1_nna_axi_clk_div.hw,
532+		[CLKID_NNA_AXI_CLK]		= &sm1_nna_axi_clk.hw,
533+		[CLKID_NNA_CORE_CLK_SEL]	= &sm1_nna_core_clk_sel.hw,
534+		[CLKID_NNA_CORE_CLK_DIV]	= &sm1_nna_core_clk_div.hw,
535+		[CLKID_NNA_CORE_CLK]		= &sm1_nna_core_clk.hw,
536+		[CLKID_MIPI_DSI_PXCLK_SEL]	= &g12a_mipi_dsi_pxclk_sel.hw,
537+		[CLKID_MIPI_DSI_PXCLK_DIV]	= &g12a_mipi_dsi_pxclk_div.hw,
538+		[CLKID_MIPI_DSI_PXCLK]		= &g12a_mipi_dsi_pxclk.hw,
539+		[CLKID_24M]			= &g12a_24m.hw,
540 		[NR_CLKS]			= NULL,
541 	},
542 	.num = NR_CLKS,
543@@ -4903,6 +5090,9 @@
544 		[CLKID_NNA_CORE_CLK_SEL]	= &sm1_nna_core_clk_sel.hw,
545 		[CLKID_NNA_CORE_CLK_DIV]	= &sm1_nna_core_clk_div.hw,
546 		[CLKID_NNA_CORE_CLK]		= &sm1_nna_core_clk.hw,
547+		[CLKID_MIPI_DSI_PXCLK_SEL]	= &g12a_mipi_dsi_pxclk_sel.hw,
548+		[CLKID_MIPI_DSI_PXCLK_DIV]	= &g12a_mipi_dsi_pxclk_div.hw,
549+		[CLKID_MIPI_DSI_PXCLK]		= &g12a_mipi_dsi_pxclk.hw,
550 		[NR_CLKS]			= NULL,
551 	},
552 	.num = NR_CLKS,
553@@ -5150,6 +5340,10 @@
554 	&sm1_nna_core_clk_sel,
555 	&sm1_nna_core_clk_div,
556 	&sm1_nna_core_clk,
557+	&g12a_mipi_dsi_pxclk_sel,
558+	&g12a_mipi_dsi_pxclk_div,
559+	&g12a_mipi_dsi_pxclk,
560+	&g12a_24m,
561 };
562
563 static const struct reg_sequence g12a_init_regs[] = {
564@@ -5166,6 +5360,57 @@
565
566 	xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0);
567
568+	void __iomem *clk_base;
569+
570+	clk_base = of_iomap(of_get_parent(pdev->dev.of_node), 0);
571+	if (!clk_base) {
572+		pr_err("%s: Unable to map clk base\n", __func__);
573+		return -1;
574+	}
575+
576+	cts_mipi_isp_clk_mux.reg = clk_base
577+		+ (unsigned long)(cts_mipi_isp_clk_mux.reg);
578+	cts_mipi_isp_clk_gate.reg = clk_base
579+		+ (unsigned long)(cts_mipi_isp_clk_gate.reg);
580+	cts_mipi_isp_clk_div.reg = clk_base
581+		+ (unsigned long)(cts_mipi_isp_clk_div.reg);
582+
583+	cts_mipi_csi_phy_clk0_mux.reg = clk_base
584+		+ (unsigned long)(cts_mipi_csi_phy_clk0_mux.reg);
585+	cts_mipi_csi_phy_clk0_div.reg = clk_base
586+		+ (unsigned long)(cts_mipi_csi_phy_clk0_div.reg);
587+	cts_mipi_csi_phy_clk0_gate.reg = clk_base
588+		+ (unsigned long)(cts_mipi_csi_phy_clk0_gate.reg);
589+
590+	// register composite clks
591+	hws[CLKID_MIPI_ISP_CLK_COMP] = clk_hw_register_composite(NULL,
592+		"cts_mipi_isp_clk_composite",
593+		media_parent_names, 8,
594+		&cts_mipi_isp_clk_mux.hw,
595+		&clk_mux_ops,
596+		&cts_mipi_isp_clk_div.hw,
597+		&clk_divider_ops,
598+		&cts_mipi_isp_clk_gate.hw,
599+		&clk_gate_ops, 0);
600+	if (IS_ERR(hws[CLKID_MIPI_ISP_CLK_COMP]))
601+		panic("%s: %d register cts_mipi_isp_clk_composite error\n",
602+			__func__, __LINE__);
603+
604+	hws[CLKID_MIPI_CSI_PHY_CLK0_COMP] = clk_hw_register_composite(NULL,
605+		"cts_mipi_csi_phy_clk0_composite",
606+		media_parent_names_mipi, 8,
607+		&cts_mipi_csi_phy_clk0_mux.hw,
608+		&clk_mux_ops,
609+		&cts_mipi_csi_phy_clk0_div.hw,
610+		&clk_divider_ops,
611+		&cts_mipi_csi_phy_clk0_gate.hw,
612+		&clk_gate_ops, 0);
613+	if (IS_ERR(hws[CLKID_MIPI_CSI_PHY_CLK0_COMP]))
614+		panic("%s: %d register cts_mipi_csi_phy_clk0_composite error\n",
615+			__func__, __LINE__);
616+
617+	meson_g12a_vcodec_init(hws, clk_base);
618+
619 	/* Setup clock notifier for cpu_clk_postmux0 */
620 	g12a_cpu_clk_postmux0_nb_data.xtal = xtal;
621 	notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw);
622diff -Naur a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h
623--- a/drivers/clk/meson/g12a.h	2022-12-19 17:13:11.813508635 +0800
624+++ b/drivers/clk/meson/g12a.h	2023-02-23 17:02:04.951750958 +0800
625@@ -44,6 +44,7 @@
626 #define HHI_PCIE_PLL_CNTL4		0x0A8
627 #define HHI_PCIE_PLL_CNTL5		0x0AC
628 #define HHI_PCIE_PLL_STS		0x0B8
629+#define HHI_XTAL_DIVN_CNTL		0x0BC /* 0x2f offset in data sheet */
630 #define HHI_HIFI_PLL_CNTL0		0x0D8
631 #define HHI_HIFI_PLL_CNTL1		0x0DC
632 #define HHI_HIFI_PLL_CNTL2		0x0E0
633@@ -70,6 +71,7 @@
634 #define HHI_MALI_CLK_CNTL		0x1b0
635 #define HHI_VPU_CLKC_CNTL		0x1b4
636 #define HHI_VPU_CLK_CNTL		0x1bC
637+#define HHI_MIPI_ISP_CLK_CNTL		0x1C0 /* 0x70 offset in data sheet */
638 #define HHI_NNA_CLK_CNTL		0x1C8
639 #define HHI_HDMI_CLK_CNTL		0x1CC
640 #define HHI_VDEC_CLK_CNTL		0x1E0
641@@ -117,6 +119,7 @@
642 #define HHI_HDMI_PLL_CNTL4		0x330
643 #define HHI_HDMI_PLL_CNTL5		0x334
644 #define HHI_HDMI_PLL_CNTL6		0x338
645+#define HHI_MIPI_CSI_PHY_CLK_CNTL	0x340 /* 0xd0 offset in data sheet */
646 #define HHI_SPICC_CLK_CNTL		0x3dc
647 #define HHI_SYS1_PLL_CNTL0		0x380
648 #define HHI_SYS1_PLL_CNTL1		0x384
649@@ -264,8 +267,9 @@
650 #define CLKID_NNA_AXI_CLK_DIV			263
651 #define CLKID_NNA_CORE_CLK_SEL			265
652 #define CLKID_NNA_CORE_CLK_DIV			266
653+#define CLKID_MIPI_DSI_PXCLK_DIV		268
654
655-#define NR_CLKS					268
656+#define NR_CLKS					288
657
658 /* include the CLKIDs that have been made part of the DT binding */
659 #include <dt-bindings/clock/g12a-clkc.h>
660diff -Naur a/drivers/clk/meson/g12a-vcodec-clk.c b/drivers/clk/meson/g12a-vcodec-clk.c
661--- a/drivers/clk/meson/g12a-vcodec-clk.c	1970-01-01 08:00:00.000000000 +0800
662+++ b/drivers/clk/meson/g12a-vcodec-clk.c	2023-02-23 17:02:04.951750958 +0800
663@@ -0,0 +1,731 @@
664+/*
665+ * drivers/amlogic/clk/g12a/g12a_clk_media.c
666+ *
667+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
668+ *
669+ * This program is free software; you can redistribute it and/or modify
670+ * it under the terms of the GNU General Public License as published by
671+ * the Free Software Foundation; either version 2 of the License, or
672+ * (at your option) any later version.
673+ *
674+ * This program is distributed in the hope that it will be useful, but WITHOUT
675+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
676+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
677+ * more details.
678+ *
679+ */
680+
681+#include <linux/clk.h>
682+#include <linux/clk-provider.h>
683+#include <linux/of_address.h>
684+#include <linux/platform_device.h>
685+#include <linux/init.h>
686+#include <linux/slab.h>
687+
688+#include "g12a.h"
689+#include "clk-mux.h"
690+#include "g12a-vcodec-clk.h"
691+
692+
693+extern spinlock_t meson_clk_lock;
694+
695+
696+const char *g12a_dec_parent_names[] = { "fclk_div2p5", "fclk_div3",
697+	"fclk_div4", "fclk_div5", "fclk_div7", "hifi_pll", "gp0_pll", "xtal"};
698+
699+/* cts_vdec_clk */
700+static struct clk_mux vdec_p0_mux = {
701+	.reg = (void *)HHI_VDEC_CLK_CNTL,
702+	.mask = 0x7,
703+	.shift = 9,
704+	.lock = &meson_clk_lock,
705+	.hw.init = &(struct clk_init_data){
706+		.name = "vdec_p0_mux",
707+		.ops = &clk_mux_ops,
708+		.parent_names = g12a_dec_parent_names,
709+		.num_parents = 8,
710+		.flags = CLK_GET_RATE_NOCACHE,
711+	},
712+};
713+
714+static struct clk_divider vdec_p0_div = {
715+	.reg = (void *)HHI_VDEC_CLK_CNTL,
716+	.shift = 0,
717+	.width = 7,
718+	.lock = &meson_clk_lock,
719+	.hw.init = &(struct clk_init_data){
720+		.name = "vdec_p0_div",
721+		.ops = &clk_divider_ops,
722+		.parent_names = (const char *[]){ "vdec_p0_mux" },
723+		.num_parents = 1,
724+		.flags = CLK_GET_RATE_NOCACHE,
725+	},
726+};
727+
728+static struct clk_gate vdec_p0_gate = {
729+	.reg = (void *)HHI_VDEC_CLK_CNTL,
730+	.bit_idx = 8,
731+	.lock = &meson_clk_lock,
732+	.hw.init = &(struct clk_init_data) {
733+		.name = "vdec_p0_gate",
734+		.ops = &clk_gate_ops,
735+		.parent_names = (const char *[]){ "vdec_p0_div" },
736+		.num_parents = 1,
737+		.flags = CLK_GET_RATE_NOCACHE,
738+	},
739+};
740+
741+static struct clk_mux vdec_p1_mux = {
742+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
743+	.mask = 0x7,
744+	.shift = 9,
745+	.lock = &meson_clk_lock,
746+	.hw.init = &(struct clk_init_data){
747+		.name = "vdec_p1_mux",
748+		.ops = &clk_mux_ops,
749+		.parent_names = g12a_dec_parent_names,
750+		.num_parents = 8,
751+		.flags = CLK_GET_RATE_NOCACHE,
752+	},
753+};
754+
755+static struct clk_divider vdec_p1_div = {
756+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
757+	.shift = 0,
758+	.width = 7,
759+	.lock = &meson_clk_lock,
760+	.hw.init = &(struct clk_init_data){
761+		.name = "vdec_p1_div",
762+		.ops = &clk_divider_ops,
763+		.parent_names = (const char *[]){ "vdec_p1_mux" },
764+		.num_parents = 1,
765+		.flags = CLK_GET_RATE_NOCACHE,
766+	},
767+};
768+
769+static struct clk_gate vdec_p1_gate = {
770+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
771+	.bit_idx = 8,
772+	.lock = &meson_clk_lock,
773+	.hw.init = &(struct clk_init_data) {
774+		.name = "vdec_p1_gate",
775+		.ops = &clk_gate_ops,
776+		.parent_names = (const char *[]){ "vdec_p1_div" },
777+		.num_parents = 1,
778+		.flags = CLK_GET_RATE_NOCACHE,
779+	},
780+};
781+
782+static struct clk_mux vdec_mux = {
783+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
784+	.mask = 0x1,
785+	.shift = 15,
786+	.lock = &meson_clk_lock,
787+	.flags = CLK_PARENT_ALTERNATE,
788+	.hw.init = &(struct clk_init_data){
789+		.name = "vdec_mux",
790+		.ops = &meson_clk_mux_ops,
791+		.parent_names = (const char *[]){ "vdec_p0_composite",
792+			"vdec_p1_composite"},
793+		.num_parents = 2,
794+		.flags = CLK_GET_RATE_NOCACHE,
795+	},
796+};
797+
798+/* cts_hcodec_clk */
799+static struct clk_mux hcodec_p0_mux = {
800+	.reg = (void *)HHI_VDEC_CLK_CNTL,
801+	.mask = 0x7,
802+	.shift = 25,
803+	.lock = &meson_clk_lock,
804+	.hw.init = &(struct clk_init_data){
805+		.name = "hcodec_p0_mux",
806+		.ops = &clk_mux_ops,
807+		.parent_names = g12a_dec_parent_names,
808+		.num_parents = 8,
809+		.flags = CLK_GET_RATE_NOCACHE,
810+	},
811+};
812+
813+static struct clk_divider hcodec_p0_div = {
814+	.reg = (void *)HHI_VDEC_CLK_CNTL,
815+	.shift = 16,
816+	.width = 7,
817+	.lock = &meson_clk_lock,
818+	.hw.init = &(struct clk_init_data){
819+		.name = "hcodec_p0_div",
820+		.ops = &clk_divider_ops,
821+		.parent_names = (const char *[]){ "hcodec_p0_mux" },
822+		.num_parents = 1,
823+		.flags = CLK_GET_RATE_NOCACHE,
824+	},
825+};
826+
827+static struct clk_gate hcodec_p0_gate = {
828+	.reg = (void *)HHI_VDEC_CLK_CNTL,
829+	.bit_idx = 24,
830+	.lock = &meson_clk_lock,
831+	.hw.init = &(struct clk_init_data) {
832+		.name = "hcodec_p0_gate",
833+		.ops = &clk_gate_ops,
834+		.parent_names = (const char *[]){ "hcodec_p0_div" },
835+		.num_parents = 1,
836+		.flags = CLK_GET_RATE_NOCACHE,
837+	},
838+};
839+
840+static struct clk_mux hcodec_p1_mux = {
841+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
842+	.mask = 0x7,
843+	.shift = 25,
844+	.lock = &meson_clk_lock,
845+	.hw.init = &(struct clk_init_data){
846+		.name = "hcodec_p1_mux",
847+		.ops = &clk_mux_ops,
848+		.parent_names = g12a_dec_parent_names,
849+		.num_parents = 8,
850+		.flags = CLK_GET_RATE_NOCACHE,
851+	},
852+};
853+
854+static struct clk_divider hcodec_p1_div = {
855+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
856+	.shift = 16,
857+	.width = 7,
858+	.lock = &meson_clk_lock,
859+	.hw.init = &(struct clk_init_data){
860+		.name = "hcodec_p1_div",
861+		.ops = &clk_divider_ops,
862+		.parent_names = (const char *[]){ "hcodec_p1_mux" },
863+		.num_parents = 1,
864+		.flags = CLK_GET_RATE_NOCACHE,
865+	},
866+};
867+
868+static struct clk_gate hcodec_p1_gate = {
869+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
870+	.bit_idx = 24,
871+	.lock = &meson_clk_lock,
872+	.hw.init = &(struct clk_init_data) {
873+		.name = "hcodec_p1_gate",
874+		.ops = &clk_gate_ops,
875+		.parent_names = (const char *[]){ "hcodec_p1_div" },
876+		.num_parents = 1,
877+		.flags = CLK_GET_RATE_NOCACHE,
878+	},
879+};
880+
881+static struct clk_mux hcodec_mux = {
882+	.reg = (void *)HHI_VDEC3_CLK_CNTL,
883+	.mask = 0x1,
884+	.shift = 31,
885+	.lock = &meson_clk_lock,
886+	.flags = CLK_PARENT_ALTERNATE,
887+	.hw.init = &(struct clk_init_data){
888+		.name = "hcodec_mux",
889+		.ops = &meson_clk_mux_ops,
890+		.parent_names = (const char *[]){ "hcodec_p0_composite",
891+			"hcodec_p1_composite"},
892+		.num_parents = 2,
893+		.flags = CLK_GET_RATE_NOCACHE,
894+	},
895+};
896+
897+/* cts_hevcb_clk */
898+static struct clk_mux hevc_p0_mux = {
899+	.reg = (void *)HHI_VDEC2_CLK_CNTL,
900+	.mask = 0x7,
901+	.shift = 25,
902+	.lock = &meson_clk_lock,
903+	.hw.init = &(struct clk_init_data){
904+		.name = "hevc_p0_mux",
905+		.ops = &clk_mux_ops,
906+		.parent_names = g12a_dec_parent_names,
907+		.num_parents = 8,
908+		.flags = CLK_GET_RATE_NOCACHE,
909+	},
910+};
911+
912+static struct clk_divider hevc_p0_div = {
913+	.reg = (void *)HHI_VDEC2_CLK_CNTL,
914+	.shift = 16,
915+	.width = 7,
916+	.lock = &meson_clk_lock,
917+	.hw.init = &(struct clk_init_data){
918+		.name = "hevc_p0_div",
919+		.ops = &clk_divider_ops,
920+		.parent_names = (const char *[]){ "hevc_p0_mux" },
921+		.num_parents = 1,
922+		.flags = CLK_GET_RATE_NOCACHE,
923+	},
924+};
925+
926+static struct clk_gate hevc_p0_gate = {
927+	.reg = (void *)HHI_VDEC2_CLK_CNTL,
928+	.bit_idx = 24,
929+	.lock = &meson_clk_lock,
930+	.hw.init = &(struct clk_init_data) {
931+		.name = "hevc_p0_gate",
932+		.ops = &clk_gate_ops,
933+		.parent_names = (const char *[]){ "hevc_p0_div" },
934+		.num_parents = 1,
935+		.flags = CLK_GET_RATE_NOCACHE,
936+	},
937+};
938+
939+static struct clk_mux hevc_p1_mux = {
940+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
941+	.mask = 0x7,
942+	.shift = 25,
943+	.lock = &meson_clk_lock,
944+	.hw.init = &(struct clk_init_data){
945+		.name = "hevc_p1_mux",
946+		.ops = &clk_mux_ops,
947+		.parent_names = g12a_dec_parent_names,
948+		.num_parents = 8,
949+		.flags = CLK_GET_RATE_NOCACHE,
950+	},
951+};
952+
953+static struct clk_divider hevc_p1_div = {
954+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
955+	.shift = 16,
956+	.width = 7,
957+	.lock = &meson_clk_lock,
958+	.hw.init = &(struct clk_init_data){
959+		.name = "hevc_p1_div",
960+		.ops = &clk_divider_ops,
961+		.parent_names = (const char *[]){ "hevc_p1_mux" },
962+		.num_parents = 1,
963+		.flags = CLK_GET_RATE_NOCACHE,
964+	},
965+};
966+
967+static struct clk_gate hevc_p1_gate = {
968+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
969+	.bit_idx = 24,
970+	.lock = &meson_clk_lock,
971+	.hw.init = &(struct clk_init_data) {
972+		.name = "hevc_p1_gate",
973+		.ops = &clk_gate_ops,
974+		.parent_names = (const char *[]){ "hevc_p1_div" },
975+		.num_parents = 1,
976+		.flags = CLK_GET_RATE_NOCACHE,
977+	},
978+};
979+
980+static struct clk_mux hevc_mux = {
981+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
982+	.mask = 0x1,
983+	.shift = 31,
984+	.lock = &meson_clk_lock,
985+	.flags = CLK_PARENT_ALTERNATE,
986+	.hw.init = &(struct clk_init_data){
987+		.name = "hevc_mux",
988+		.ops = &meson_clk_mux_ops,
989+		.parent_names = (const char *[]){ "hevc_p0_composite",
990+			"hevc_p1_composite"},
991+		.num_parents = 2,
992+		.flags = CLK_GET_RATE_NOCACHE,
993+	},
994+};
995+
996+/* cts_hevcf_clk */
997+static struct clk_mux hevcf_p0_mux = {
998+	.reg = (void *)HHI_VDEC2_CLK_CNTL,
999+	.mask = 0x7,
1000+	.shift = 9,
1001+	.lock = &meson_clk_lock,
1002+	.hw.init = &(struct clk_init_data){
1003+		.name = "hevcf_p0_mux",
1004+		.ops = &clk_mux_ops,
1005+		.parent_names = g12a_dec_parent_names,
1006+		.num_parents = 8,
1007+		.flags = CLK_GET_RATE_NOCACHE,
1008+	},
1009+};
1010+
1011+static struct clk_divider hevcf_p0_div = {
1012+	.reg = (void *)HHI_VDEC2_CLK_CNTL,
1013+	.shift = 0,
1014+	.width = 7,
1015+	.lock = &meson_clk_lock,
1016+	.hw.init = &(struct clk_init_data){
1017+		.name = "hevcf_p0_div",
1018+		.ops = &clk_divider_ops,
1019+		.parent_names = (const char *[]){ "hevcf_p0_mux" },
1020+		.num_parents = 1,
1021+		.flags = CLK_GET_RATE_NOCACHE,
1022+	},
1023+};
1024+
1025+static struct clk_gate hevcf_p0_gate = {
1026+	.reg = (void *)HHI_VDEC2_CLK_CNTL,
1027+	.bit_idx = 8,
1028+	.lock = &meson_clk_lock,
1029+	.hw.init = &(struct clk_init_data) {
1030+		.name = "hevcf_p0_gate",
1031+		.ops = &clk_gate_ops,
1032+		.parent_names = (const char *[]){ "hevcf_p0_div" },
1033+		.num_parents = 1,
1034+		.flags = CLK_GET_RATE_NOCACHE,
1035+	},
1036+};
1037+
1038+static struct clk_mux hevcf_p1_mux = {
1039+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
1040+	.mask = 0x7,
1041+	.shift = 9,
1042+	.lock = &meson_clk_lock,
1043+	.hw.init = &(struct clk_init_data){
1044+		.name = "hevcf_p1_mux",
1045+		.ops = &clk_mux_ops,
1046+		.parent_names = g12a_dec_parent_names,
1047+		.num_parents = 8,
1048+		.flags = CLK_GET_RATE_NOCACHE,
1049+	},
1050+};
1051+
1052+static struct clk_divider hevcf_p1_div = {
1053+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
1054+	.shift = 0,
1055+	.width = 7,
1056+	.lock = &meson_clk_lock,
1057+	.hw.init = &(struct clk_init_data){
1058+		.name = "hevcf_p1_div",
1059+		.ops = &clk_divider_ops,
1060+		.parent_names = (const char *[]){ "hevcf_p1_mux" },
1061+		.num_parents = 1,
1062+		.flags = CLK_GET_RATE_NOCACHE,
1063+	},
1064+};
1065+
1066+static struct clk_gate hevcf_p1_gate = {
1067+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
1068+	.bit_idx = 8,
1069+	.lock = &meson_clk_lock,
1070+	.hw.init = &(struct clk_init_data) {
1071+		.name = "hevcf_p1_gate",
1072+		.ops = &clk_gate_ops,
1073+		.parent_names = (const char *[]){ "hevcf_p1_div" },
1074+		.num_parents = 1,
1075+		.flags = CLK_GET_RATE_NOCACHE,
1076+	},
1077+};
1078+
1079+static struct clk_mux hevcf_mux = {
1080+	.reg = (void *)HHI_VDEC4_CLK_CNTL,
1081+	.mask = 0x1,
1082+	.shift = 15,
1083+	.lock = &meson_clk_lock,
1084+	.flags = CLK_PARENT_ALTERNATE,
1085+	.hw.init = &(struct clk_init_data){
1086+		.name = "hevcf_mux",
1087+		.ops = &meson_clk_mux_ops,
1088+		.parent_names = (const char *[]){ "hevcf_p0_composite",
1089+			"hevcf_p1_composite"},
1090+		.num_parents = 2,
1091+		.flags = CLK_GET_RATE_NOCACHE,
1092+	},
1093+};
1094+
1095+static const char * const vpu_clkb_tmp_parent_names[] = { "vpu",
1096+	"fclk_div4", "fclk_div5", "fclk_div7"};
1097+
1098+static struct clk_mux vpu_clkb_tmp_mux = {
1099+	.reg = (void *)HHI_VPU_CLKB_CNTL,
1100+	.mask = 0x3,
1101+	.shift = 20,
1102+	.lock = &meson_clk_lock,
1103+	.hw.init = &(struct clk_init_data){
1104+		.name = "vpu_clkb_tmp_mux",
1105+		.ops = &clk_mux_ops,
1106+		.parent_names = vpu_clkb_tmp_parent_names,
1107+		.num_parents = ARRAY_SIZE(vpu_clkb_tmp_parent_names),
1108+		.flags = CLK_GET_RATE_NOCACHE,
1109+	},
1110+};
1111+
1112+static struct clk_divider vpu_clkb_tmp_div = {
1113+	.reg = (void *)HHI_VPU_CLKB_CNTL,
1114+	.shift = 16,
1115+	.width = 4,
1116+	.lock = &meson_clk_lock,
1117+	.hw.init = &(struct clk_init_data){
1118+		.name = "vpu_clkb_tmp_div",
1119+		.ops = &clk_divider_ops,
1120+		.parent_names = (const char *[]){ "vpu_clkb_tmp_mux" },
1121+		.num_parents = 1,
1122+		.flags = CLK_GET_RATE_NOCACHE,
1123+	},
1124+};
1125+
1126+static struct clk_gate vpu_clkb_tmp_gate = {
1127+	.reg = (void *)HHI_VPU_CLKB_CNTL,
1128+	.bit_idx = 24,
1129+	.lock = &meson_clk_lock,
1130+	.hw.init = &(struct clk_init_data) {
1131+		.name = "vpu_clkb_tmp_gate",
1132+		.ops = &clk_gate_ops,
1133+		.parent_names = (const char *[]){ "vpu_clkb_tmp_div" },
1134+		.num_parents = 1,
1135+		.flags = CLK_GET_RATE_NOCACHE,
1136+	},
1137+};
1138+
1139+static const char * const vpu_clkb_parent_names[]
1140+						= { "vpu_clkb_tmp_composite" };
1141+
1142+static struct clk_divider vpu_clkb_div = {
1143+	.reg = (void *)HHI_VPU_CLKB_CNTL,
1144+	.shift = 0,
1145+	.width = 8,
1146+	.lock = &meson_clk_lock,
1147+	.hw.init = &(struct clk_init_data){
1148+		.name = "vpu_clkb_div",
1149+		.ops = &clk_divider_ops,
1150+		.parent_names = (const char *[]){ "vpu_clkb_tmp_composite" },
1151+		.num_parents = 1,
1152+		.flags = CLK_GET_RATE_NOCACHE,
1153+	},
1154+};
1155+
1156+static struct clk_gate vpu_clkb_gate = {
1157+	.reg = (void *)HHI_VPU_CLKB_CNTL,
1158+	.bit_idx = 8,
1159+	.lock = &meson_clk_lock,
1160+	.hw.init = &(struct clk_init_data) {
1161+		.name = "vpu_clkb_gate",
1162+		.ops = &clk_gate_ops,
1163+		.parent_names = (const char *[]){ "vpu_clkb_div" },
1164+		.num_parents = 1,
1165+		.flags = CLK_GET_RATE_NOCACHE,
1166+	},
1167+};
1168+
1169+void meson_g12a_vcodec_init(struct clk_hw **clk_hws, void __iomem *clk_base)
1170+{
1171+	/* cts_vdec_clk */
1172+	vdec_p0_mux.reg = clk_base + (unsigned long)(vdec_p0_mux.reg);
1173+	vdec_p0_div.reg = clk_base + (unsigned long)(vdec_p0_div.reg);
1174+	vdec_p0_gate.reg = clk_base + (unsigned long)(vdec_p0_gate.reg);
1175+	vdec_p1_mux.reg = clk_base + (unsigned long)(vdec_p1_mux.reg);
1176+	vdec_p1_div.reg = clk_base + (unsigned long)(vdec_p1_div.reg);
1177+	vdec_p1_gate.reg = clk_base + (unsigned long)(vdec_p1_gate.reg);
1178+	vdec_mux.reg = clk_base + (unsigned long)(vdec_mux.reg);
1179+
1180+	/* cts_hcodec_clk */
1181+	hcodec_p0_mux.reg = clk_base + (unsigned long)(hcodec_p0_mux.reg);
1182+	hcodec_p0_div.reg = clk_base + (unsigned long)(hcodec_p0_div.reg);
1183+	hcodec_p0_gate.reg = clk_base + (unsigned long)(hcodec_p0_gate.reg);
1184+	hcodec_p1_mux.reg = clk_base + (unsigned long)(hcodec_p1_mux.reg);
1185+	hcodec_p1_div.reg = clk_base + (unsigned long)(hcodec_p1_div.reg);
1186+	hcodec_p1_gate.reg = clk_base + (unsigned long)(hcodec_p1_gate.reg);
1187+	hcodec_mux.reg = clk_base + (unsigned long)(hcodec_mux.reg);
1188+
1189+	/* cts_hevc_clk */
1190+	hevc_p0_mux.reg = clk_base + (unsigned long)(hevc_p0_mux.reg);
1191+	hevc_p0_div.reg = clk_base + (unsigned long)(hevc_p0_div.reg);
1192+	hevc_p0_gate.reg = clk_base + (unsigned long)(hevc_p0_gate.reg);
1193+	hevc_p1_mux.reg = clk_base + (unsigned long)(hevc_p1_mux.reg);
1194+	hevc_p1_div.reg = clk_base + (unsigned long)(hevc_p1_div.reg);
1195+	hevc_p1_gate.reg = clk_base + (unsigned long)(hevc_p1_gate.reg);
1196+	hevc_mux.reg = clk_base + (unsigned long)(hevc_mux.reg);
1197+
1198+	/* cts_hevcf_clk */
1199+	hevcf_p0_mux.reg = clk_base + (unsigned long)(hevcf_p0_mux.reg);
1200+	hevcf_p0_div.reg = clk_base + (unsigned long)(hevcf_p0_div.reg);
1201+	hevcf_p0_gate.reg = clk_base + (unsigned long)(hevcf_p0_gate.reg);
1202+	hevcf_p1_mux.reg = clk_base + (unsigned long)(hevcf_p1_mux.reg);
1203+	hevcf_p1_div.reg = clk_base + (unsigned long)(hevcf_p1_div.reg);
1204+	hevcf_p1_gate.reg = clk_base + (unsigned long)(hevcf_p1_gate.reg);
1205+	hevcf_mux.reg = clk_base + (unsigned long)(hevcf_mux.reg);
1206+
1207+	vpu_clkb_tmp_mux.reg = clk_base + (unsigned long)(vpu_clkb_tmp_mux.reg);
1208+	vpu_clkb_tmp_div.reg = clk_base + (unsigned long)(vpu_clkb_tmp_div.reg);
1209+	vpu_clkb_tmp_gate.reg = clk_base + (unsigned long)(vpu_clkb_tmp_gate.reg);
1210+
1211+	vpu_clkb_div.reg = clk_base + (unsigned long)(vpu_clkb_div.reg);
1212+	vpu_clkb_gate.reg = clk_base + (unsigned long)(vpu_clkb_gate.reg);
1213+
1214+	/* cts_vdec_clk */
1215+	clk_hws[CLKID_VDEC_P0_COMP] = clk_hw_register_composite(NULL,
1216+		"vdec_p0_composite",
1217+		g12a_dec_parent_names, 8,
1218+		&vdec_p0_mux.hw,
1219+		&clk_mux_ops,
1220+		&vdec_p0_div.hw,
1221+		&clk_divider_ops,
1222+		&vdec_p0_gate.hw,
1223+		&clk_gate_ops, 0);
1224+	if (IS_ERR(clk_hws[CLKID_VDEC_P0_COMP]))
1225+		panic("%s: %d clk_hw_register_composite vdec_p0_composite error\n",
1226+			__func__, __LINE__);
1227+
1228+	clk_hws[CLKID_VDEC_P1_COMP] = clk_hw_register_composite(NULL,
1229+		"vdec_p1_composite",
1230+		g12a_dec_parent_names, 8,
1231+		&vdec_p1_mux.hw,
1232+		&clk_mux_ops,
1233+		&vdec_p1_div.hw,
1234+		&clk_divider_ops,
1235+		&vdec_p1_gate.hw,
1236+		&clk_gate_ops, 0);
1237+	if (IS_ERR(clk_hws[CLKID_VDEC_P1_COMP]))
1238+		panic("%s: %d clk_hw_register_composite vdec_p1_composite error\n",
1239+			__func__, __LINE__);
1240+
1241+	if (clk_hw_register(NULL, &vdec_mux.hw)) {
1242+		panic("%s: %d clk_hw_register vdec_mux error\n",
1243+			__func__, __LINE__);
1244+	} else {
1245+		clk_hws[CLKID_VDEC_MUX] = &vdec_mux.hw;
1246+	}
1247+
1248+	if (IS_ERR(clk_hws[CLKID_VDEC_MUX]))
1249+		panic("%s: %d clk_hw_register vdec_mux error\n",
1250+			__func__, __LINE__);
1251+
1252+	/* cts_hcodec_clk */
1253+	clk_hws[CLKID_HCODEC_P0_COMP] = clk_hw_register_composite(NULL,
1254+		"hcodec_p0_composite",
1255+		g12a_dec_parent_names, 8,
1256+		&hcodec_p0_mux.hw,
1257+		&clk_mux_ops,
1258+		&hcodec_p0_div.hw,
1259+		&clk_divider_ops,
1260+		&hcodec_p0_gate.hw,
1261+		&clk_gate_ops, 0);
1262+	if (IS_ERR(clk_hws[CLKID_HCODEC_P0_COMP]))
1263+		panic("%s: %d clk_hw_register_composite hcodec_p0_composite error\n",
1264+			__func__, __LINE__);
1265+
1266+	clk_hws[CLKID_HCODEC_P1_COMP] = clk_hw_register_composite(NULL,
1267+		"hcodec_p1_composite",
1268+		g12a_dec_parent_names, 8,
1269+		&hcodec_p1_mux.hw,
1270+		&clk_mux_ops,
1271+		&hcodec_p1_div.hw,
1272+		&clk_divider_ops,
1273+		&hcodec_p1_gate.hw,
1274+		&clk_gate_ops, 0);
1275+	if (IS_ERR(clk_hws[CLKID_HCODEC_P1_COMP]))
1276+		panic("%s: %d clk_hw_register_composite hcodec_p1_composite error\n",
1277+		__func__, __LINE__);
1278+
1279+	if (clk_hw_register(NULL, &hcodec_mux.hw)) {
1280+		panic("%s: %d clk_hw_register hcodec_mux error\n",
1281+			__func__, __LINE__);
1282+	} else {
1283+		clk_hws[CLKID_HCODEC_MUX] = &hcodec_mux.hw;
1284+	}
1285+
1286+	if (IS_ERR(clk_hws[CLKID_HCODEC_MUX]))
1287+		panic("%s: %d clk_hw_register hcodec_mux error\n",
1288+			__func__, __LINE__);
1289+
1290+	/* cts_hevc_clk */
1291+	clk_hws[CLKID_HEVC_P0_COMP] = clk_hw_register_composite(NULL,
1292+		"hevc_p0_composite",
1293+		g12a_dec_parent_names, 8,
1294+		&hevc_p0_mux.hw,
1295+		&clk_mux_ops,
1296+		&hevc_p0_div.hw,
1297+		&clk_divider_ops,
1298+		&hevc_p0_gate.hw,
1299+		&clk_gate_ops, 0);
1300+	if (IS_ERR(clk_hws[CLKID_HEVC_P0_COMP]))
1301+		panic("%s: %d clk_hw_register_composite hevc_p0_composite error\n",
1302+			__func__, __LINE__);
1303+
1304+	clk_hws[CLKID_HEVC_P1_COMP] = clk_hw_register_composite(NULL,
1305+		"hevc_p1_composite",
1306+		g12a_dec_parent_names, 8,
1307+		&hevc_p1_mux.hw,
1308+		&clk_mux_ops,
1309+		&hevc_p1_div.hw,
1310+		&clk_divider_ops,
1311+		&hevc_p1_gate.hw,
1312+		&clk_gate_ops, 0);
1313+	if (IS_ERR(clk_hws[CLKID_HEVC_P1_COMP]))
1314+		panic("%s: %d clk_hw_register_composite hevc_p1_composite error\n",
1315+		__func__, __LINE__);
1316+
1317+	if (clk_hw_register(NULL, &hevc_mux.hw)) {
1318+		panic("%s: %d clk_hw_register hcodec_mux error\n",
1319+			__func__, __LINE__);
1320+	} else {
1321+		clk_hws[CLKID_HEVC_MUX] = &hevc_mux.hw;
1322+	}
1323+
1324+	if (IS_ERR(clk_hws[CLKID_HEVC_MUX]))
1325+		panic("%s: %d clk_hw_register hevc_mux error\n",
1326+			__func__, __LINE__);
1327+
1328+	/* cts_hevcf_clk */
1329+	clk_hws[CLKID_HEVCF_P0_COMP] = clk_hw_register_composite(NULL,
1330+		"hevcf_p0_composite",
1331+		g12a_dec_parent_names, 8,
1332+		 &hevcf_p0_mux.hw,
1333+		&clk_mux_ops,
1334+		&hevcf_p0_div.hw,
1335+		&clk_divider_ops,
1336+		&hevcf_p0_gate.hw,
1337+		&clk_gate_ops, 0);
1338+	if (IS_ERR(clk_hws[CLKID_HEVCF_P0_COMP]))
1339+		panic("%s: %d clk_hw_register_composite hevcf_p0_composite error\n",
1340+			__func__, __LINE__);
1341+
1342+	clk_hws[CLKID_HEVCF_P1_COMP] = clk_hw_register_composite(NULL,
1343+		"hevcf_p1_composite",
1344+		g12a_dec_parent_names, 8,
1345+		&hevcf_p1_mux.hw,
1346+		&clk_mux_ops,
1347+		&hevcf_p1_div.hw,
1348+		&clk_divider_ops,
1349+		&hevcf_p1_gate.hw,
1350+		&clk_gate_ops, 0);
1351+	if (IS_ERR(clk_hws[CLKID_HEVCF_P1_COMP]))
1352+		panic("%s: %d clk_hw_register_composite hevcf_p1_composite error\n",
1353+		__func__, __LINE__);
1354+
1355+	if (clk_hw_register(NULL, &hevcf_mux.hw)) {
1356+		panic("%s: %d clk_hw_register hevcf_mux error\n",
1357+			__func__, __LINE__);
1358+	} else {
1359+		clk_hws[CLKID_HEVCF_MUX] = &hevcf_mux.hw;
1360+	}
1361+
1362+	if (IS_ERR(clk_hws[CLKID_HEVCF_MUX]))
1363+		panic("%s: %d clk_hw_register hevcf_mux error\n",
1364+			__func__, __LINE__);
1365+
1366+	clk_hws[CLKID_VPU_CLKB_TMP_COMP] = clk_hw_register_composite(NULL,
1367+			"vpu_clkb_tmp_composite",
1368+			vpu_clkb_tmp_parent_names, 4,
1369+			&vpu_clkb_tmp_mux.hw,
1370+			&clk_mux_ops,
1371+			&vpu_clkb_tmp_div.hw,
1372+			&clk_divider_ops,
1373+			&vpu_clkb_tmp_gate.hw,
1374+			&clk_gate_ops, 0);
1375+	if (IS_ERR(clk_hws[CLKID_VPU_CLKB_TMP_COMP]))
1376+		panic("%s: %d clk_register_composite vpu_clkb_tmp_composite error\n",
1377+			__func__, __LINE__);
1378+
1379+	clk_hws[CLKID_VPU_CLKB_COMP] = clk_hw_register_composite(NULL,
1380+			"vpu_clkb_composite",
1381+			vpu_clkb_parent_names, 1,
1382+			NULL,
1383+			NULL,
1384+			&vpu_clkb_div.hw,
1385+			&clk_divider_ops,
1386+			&vpu_clkb_gate.hw,
1387+			&clk_gate_ops, 0);
1388+	if (IS_ERR(clk_hws[CLKID_VPU_CLKB_COMP]))
1389+		panic("%s: %d clk_register_composite vpu_clkb_composite error\n",
1390+			__func__, __LINE__);
1391+
1392+	pr_info("%s: register meson media clk\n", __func__);
1393+}
1394+
1395diff -Naur a/drivers/clk/meson/g12a-vcodec-clk.h b/drivers/clk/meson/g12a-vcodec-clk.h
1396--- a/drivers/clk/meson/g12a-vcodec-clk.h	1970-01-01 08:00:00.000000000 +0800
1397+++ b/drivers/clk/meson/g12a-vcodec-clk.h	2023-02-23 17:02:04.951750958 +0800
1398@@ -0,0 +1,12 @@
1399+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
1400+/*
1401+ * Copyright (c) 2019 BayLibre, SAS
1402+ * Author: Neil Armstrong <narmstrong@baylibre.com>
1403+ */
1404+
1405+#ifndef __G12A_VCODEC_CLK_H
1406+#define __G12A_VCODEC_CLK_H
1407+
1408+extern void meson_g12a_vcodec_init(struct clk_hw **clks, void __iomem *clk_base);
1409+
1410+#endif /* __G12A_VCODEC_CLK_H */
1411diff -Naur a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
1412--- a/drivers/clk/meson/Makefile	2022-12-19 17:13:11.809508587 +0800
1413+++ b/drivers/clk/meson/Makefile	2023-02-23 17:02:04.951750958 +0800
1414@@ -7,7 +7,7 @@
1415 obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o
1416 obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o
1417 obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o
1418-obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o
1419+obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o clk-mux.o
1420 obj-$(CONFIG_COMMON_CLK_MESON_REGMAP) += clk-regmap.o
1421 obj-$(CONFIG_COMMON_CLK_MESON_SCLK_DIV) += sclk-div.o
1422 obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o
1423@@ -17,5 +17,5 @@
1424 obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
1425 obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
1426 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
1427-obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
1428+obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o g12a-vcodec-clk.o
1429 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
1430diff -Naur a/drivers/clk/meson/vid-pll-div.c b/drivers/clk/meson/vid-pll-div.c
1431--- a/drivers/clk/meson/vid-pll-div.c	2022-12-19 17:13:11.813508635 +0800
1432+++ b/drivers/clk/meson/vid-pll-div.c	2023-02-23 17:02:04.951750958 +0800
1433@@ -39,12 +39,14 @@
1434 	}
1435
1436 static const struct vid_pll_div vid_pll_div_table[] = {
1437+	VID_PLL_DIV(0xffff, 0, 1, 1),	/* 1/1  => /1 */
1438 	VID_PLL_DIV(0x0aaa, 0, 2, 1),	/* 2/1  => /2 */
1439 	VID_PLL_DIV(0x5294, 2, 5, 2),	/* 5/2  => /2.5 */
1440 	VID_PLL_DIV(0x0db6, 0, 3, 1),	/* 3/1  => /3 */
1441 	VID_PLL_DIV(0x36cc, 1, 7, 2),	/* 7/2  => /3.5 */
1442 	VID_PLL_DIV(0x6666, 2, 15, 4),	/* 15/4 => /3.75 */
1443 	VID_PLL_DIV(0x0ccc, 0, 4, 1),	/* 4/1  => /4 */
1444+	VID_PLL_DIV(0x0ccc, 1, 467, 100), /* 467/100  => /4.67 */
1445 	VID_PLL_DIV(0x739c, 2, 5, 1),	/* 5/1  => /5 */
1446 	VID_PLL_DIV(0x0e38, 0, 6, 1),	/* 6/1  => /6 */
1447 	VID_PLL_DIV(0x0000, 3, 25, 4),	/* 25/4 => /6.25 */
1448diff -Naur a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
1449--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c	2022-12-19 17:13:12.585517887 +0800
1450+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c	2023-02-23 17:02:04.951750958 +0800
1451@@ -143,6 +143,7 @@
1452 struct dw_hdmi {
1453 	struct drm_connector connector;
1454 	struct drm_bridge bridge;
1455+	struct drm_bridge *next_bridge;
1456
1457 	unsigned int version;
1458
1459@@ -754,6 +755,11 @@
1460 	else
1461 		hdmi->mc_clkdis |= HDMI_MC_CLKDIS_AUDCLK_DISABLE;
1462 	hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
1463+
1464+	 if (enable) {
1465+		hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
1466+		hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
1467+	}
1468 }
1469
1470 static u8 *hdmi_audio_get_eld(struct dw_hdmi *hdmi)
1471@@ -2403,21 +2409,6 @@
1472 	return ret;
1473 }
1474
1475-static bool hdr_metadata_equal(const struct drm_connector_state *old_state,
1476-			       const struct drm_connector_state *new_state)
1477-{
1478-	struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
1479-	struct drm_property_blob *new_blob = new_state->hdr_output_metadata;
1480-
1481-	if (!old_blob || !new_blob)
1482-		return old_blob == new_blob;
1483-
1484-	if (old_blob->length != new_blob->length)
1485-		return false;
1486-
1487-	return !memcmp(old_blob->data, new_blob->data, old_blob->length);
1488-}
1489-
1490 static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
1491 					  struct drm_atomic_state *state)
1492 {
1493@@ -2431,7 +2422,7 @@
1494 	if (!crtc)
1495 		return 0;
1496
1497-	if (!hdr_metadata_equal(old_state, new_state)) {
1498+	if (!drm_connector_atomic_hdr_metadata_equal(old_state, new_state)) {
1499 		crtc_state = drm_atomic_get_crtc_state(state, crtc);
1500 		if (IS_ERR(crtc_state))
1501 			return PTR_ERR(crtc_state);
1502@@ -2500,8 +2491,7 @@
1503 	drm_connector_attach_max_bpc_property(connector, 8, 16);
1504
1505 	if (hdmi->version >= 0x200a && hdmi->plat_data->use_drm_infoframe)
1506-		drm_object_attach_property(&connector->base,
1507-			connector->dev->mode_config.hdr_output_metadata_property, 0);
1508+		drm_connector_attach_hdr_output_metadata_property(connector);
1509
1510 	drm_connector_attach_encoder(connector, hdmi->bridge.encoder);
1511
1512@@ -2800,7 +2790,8 @@
1513 	struct dw_hdmi *hdmi = bridge->driver_private;
1514
1515 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
1516-		return 0;
1517+		return drm_bridge_attach(bridge->encoder, hdmi->next_bridge,
1518+					 bridge, flags);
1519
1520 	return dw_hdmi_connector_create(hdmi);
1521 }
1522@@ -3185,6 +3176,52 @@
1523 /* -----------------------------------------------------------------------------
1524  * Probe/remove API, used from platforms based on the DRM bridge API.
1525  */
1526+
1527+static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi)
1528+{
1529+	struct device_node *endpoint;
1530+	struct device_node *remote;
1531+
1532+	if (!hdmi->plat_data->output_port)
1533+		return 0;
1534+
1535+	endpoint = of_graph_get_endpoint_by_regs(hdmi->dev->of_node,
1536+						 hdmi->plat_data->output_port,
1537+						 -1);
1538+	if (!endpoint) {
1539+		/*
1540+		 * On platforms whose bindings don't make the output port
1541+		 * mandatory (such as Rockchip) the plat_data->output_port
1542+		 * field isn't set, so it's safe to make this a fatal error.
1543+		 */
1544+		dev_err(hdmi->dev, "Missing endpoint in port@%u\n",
1545+			hdmi->plat_data->output_port);
1546+		return -ENODEV;
1547+	}
1548+
1549+	remote = of_graph_get_remote_port_parent(endpoint);
1550+	of_node_put(endpoint);
1551+	if (!remote) {
1552+		dev_err(hdmi->dev, "Endpoint in port@%u unconnected\n",
1553+			hdmi->plat_data->output_port);
1554+		return -ENODEV;
1555+	}
1556+
1557+	if (!of_device_is_available(remote)) {
1558+		dev_err(hdmi->dev, "port@%u remote device is disabled\n",
1559+			hdmi->plat_data->output_port);
1560+		of_node_put(remote);
1561+		return -ENODEV;
1562+	}
1563+
1564+	hdmi->next_bridge = of_drm_find_bridge(remote);
1565+	of_node_put(remote);
1566+	if (!hdmi->next_bridge)
1567+		return -EPROBE_DEFER;
1568+
1569+	return 0;
1570+}
1571+
1572 struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
1573 			      const struct dw_hdmi_plat_data *plat_data)
1574 {
1575@@ -3221,6 +3258,10 @@
1576 	mutex_init(&hdmi->cec_notifier_mutex);
1577 	spin_lock_init(&hdmi->audio_lock);
1578
1579+	ret = dw_hdmi_parse_dt(hdmi);
1580+	if (ret < 0)
1581+		return ERR_PTR(ret);
1582+
1583 	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
1584 	if (ddc_node) {
1585 		hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
1586@@ -3386,6 +3427,7 @@
1587 	hdmi->bridge.funcs = &dw_hdmi_bridge_funcs;
1588 	hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
1589 			 | DRM_BRIDGE_OP_HPD;
1590+	hdmi->bridge.interlace_allowed = true;
1591 #ifdef CONFIG_OF
1592 	hdmi->bridge.of_node = pdev->dev.of_node;
1593 #endif
1594@@ -3430,7 +3472,7 @@
1595 		hdmi->audio = platform_device_register_full(&pdevinfo);
1596 	}
1597
1598-	if (config0 & HDMI_CONFIG0_CEC) {
1599+	if (!plat_data->disable_cec && (config0 & HDMI_CONFIG0_CEC)) {
1600 		cec.hdmi = hdmi;
1601 		cec.ops = &dw_hdmi_cec_ops;
1602 		cec.irq = irq;
1603@@ -3449,8 +3491,7 @@
1604
1605 err_iahb:
1606 	clk_disable_unprepare(hdmi->iahb_clk);
1607-	if (hdmi->cec_clk)
1608-		clk_disable_unprepare(hdmi->cec_clk);
1609+	clk_disable_unprepare(hdmi->cec_clk);
1610 err_isfr:
1611 	clk_disable_unprepare(hdmi->isfr_clk);
1612 err_res:
1613@@ -3474,8 +3515,7 @@
1614
1615 	clk_disable_unprepare(hdmi->iahb_clk);
1616 	clk_disable_unprepare(hdmi->isfr_clk);
1617-	if (hdmi->cec_clk)
1618-		clk_disable_unprepare(hdmi->cec_clk);
1619+	clk_disable_unprepare(hdmi->cec_clk);
1620
1621 	if (hdmi->i2c)
1622 		i2c_del_adapter(&hdmi->i2c->adap);
1623diff -Naur a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
1624--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c	2022-12-19 17:13:12.585517887 +0800
1625+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c	2023-02-23 17:02:04.951750958 +0800
1626@@ -265,11 +265,9 @@
1627 	/* override the module pointer */
1628 	cec->adap->owner = THIS_MODULE;
1629
1630-	ret = devm_add_action(&pdev->dev, dw_hdmi_cec_del, cec);
1631-	if (ret) {
1632-		cec_delete_adapter(cec->adap);
1633+	ret = devm_add_action_or_reset(&pdev->dev, dw_hdmi_cec_del, cec);
1634+	if (ret)
1635 		return ret;
1636-	}
1637
1638 	ret = devm_request_threaded_irq(&pdev->dev, cec->irq,
1639 					dw_hdmi_cec_hardirq,
1640diff -Naur a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
1641--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c	2022-12-19 17:13:12.589517935 +0800
1642+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c	2023-02-23 17:02:04.951750958 +0800
1643@@ -246,6 +246,7 @@
1644
1645 	struct clk *pclk;
1646
1647+	bool device_found;
1648 	unsigned int lane_mbps; /* per lane */
1649 	u32 channel;
1650 	u32 lanes;
1651@@ -309,13 +310,37 @@
1652 	return readl(dsi->base + reg);
1653 }
1654
1655+static int dw_mipi_dsi_panel_or_bridge(struct dw_mipi_dsi *dsi,
1656+				       struct device_node *node)
1657+{
1658+	struct drm_bridge *bridge;
1659+	struct drm_panel *panel;
1660+	int ret;
1661+
1662+	ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
1663+	if (ret)
1664+		return ret;
1665+
1666+	if (panel) {
1667+		bridge = drm_panel_bridge_add_typed(panel,
1668+						    DRM_MODE_CONNECTOR_DSI);
1669+		if (IS_ERR(bridge))
1670+			return PTR_ERR(bridge);
1671+	}
1672+
1673+	dsi->panel_bridge = bridge;
1674+
1675+	if (!dsi->panel_bridge)
1676+		return -EPROBE_DEFER;
1677+
1678+	return 0;
1679+}
1680+
1681 static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
1682 				   struct mipi_dsi_device *device)
1683 {
1684 	struct dw_mipi_dsi *dsi = host_to_dsi(host);
1685 	const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
1686-	struct drm_bridge *bridge;
1687-	struct drm_panel *panel;
1688 	int ret;
1689
1690 	if (device->lanes > dsi->plat_data->max_data_lanes) {
1691@@ -329,22 +354,14 @@
1692 	dsi->format = device->format;
1693 	dsi->mode_flags = device->mode_flags;
1694
1695-	ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0,
1696-					  &panel, &bridge);
1697-	if (ret)
1698-		return ret;
1699+	if (!dsi->device_found) {
1700+		ret = dw_mipi_dsi_panel_or_bridge(dsi, host->dev->of_node);
1701+		if (ret)
1702+			return ret;
1703
1704-	if (panel) {
1705-		bridge = drm_panel_bridge_add_typed(panel,
1706-						    DRM_MODE_CONNECTOR_DSI);
1707-		if (IS_ERR(bridge))
1708-			return PTR_ERR(bridge);
1709+		dsi->device_found = true;
1710 	}
1711
1712-	dsi->panel_bridge = bridge;
1713-
1714-	drm_bridge_add(&dsi->bridge);
1715-
1716 	if (pdata->host_ops && pdata->host_ops->attach) {
1717 		ret = pdata->host_ops->attach(pdata->priv_data, device);
1718 		if (ret < 0)
1719@@ -854,7 +871,8 @@
1720 	dsi_write(dsi, DSI_INT_MSK1, 0);
1721 }
1722
1723-static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
1724+static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
1725+						   struct drm_bridge_state *old_bridge_state)
1726 {
1727 	struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
1728 	const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
1729@@ -961,7 +979,8 @@
1730 		dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
1731 }
1732
1733-static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
1734+static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
1735+					     struct drm_bridge_state *old_bridge_state)
1736 {
1737 	struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
1738
1739@@ -981,7 +1000,10 @@
1740 	enum drm_mode_status mode_status = MODE_OK;
1741
1742 	if (pdata->mode_valid)
1743-		mode_status = pdata->mode_valid(pdata->priv_data, mode);
1744+		mode_status = pdata->mode_valid(pdata->priv_data, mode,
1745+						dsi->mode_flags,
1746+						dw_mipi_dsi_get_lanes(dsi),
1747+						dsi->format);
1748
1749 	return mode_status;
1750 }
1751@@ -999,17 +1021,30 @@
1752 	/* Set the encoder type as caller does not know it */
1753 	bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
1754
1755+	if (!dsi->device_found) {
1756+		int ret;
1757+
1758+		ret = dw_mipi_dsi_panel_or_bridge(dsi, dsi->dev->of_node);
1759+		if (ret)
1760+			return ret;
1761+
1762+		dsi->device_found = true;
1763+	}
1764+
1765 	/* Attach the panel-bridge to the dsi bridge */
1766 	return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
1767 				 flags);
1768 }
1769
1770 static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
1771-	.mode_set     = dw_mipi_dsi_bridge_mode_set,
1772-	.enable	      = dw_mipi_dsi_bridge_enable,
1773-	.post_disable = dw_mipi_dsi_bridge_post_disable,
1774-	.mode_valid   = dw_mipi_dsi_bridge_mode_valid,
1775-	.attach	      = dw_mipi_dsi_bridge_attach,
1776+	.atomic_duplicate_state	= drm_atomic_helper_bridge_duplicate_state,
1777+	.atomic_destroy_state	= drm_atomic_helper_bridge_destroy_state,
1778+	.atomic_reset		= drm_atomic_helper_bridge_reset,
1779+	.atomic_enable		= dw_mipi_dsi_bridge_atomic_enable,
1780+	.atomic_post_disable	= dw_mipi_dsi_bridge_post_atomic_disable,
1781+	.mode_set		= dw_mipi_dsi_bridge_mode_set,
1782+	.mode_valid		= dw_mipi_dsi_bridge_mode_valid,
1783+	.attach			= dw_mipi_dsi_bridge_attach,
1784 };
1785
1786 #ifdef CONFIG_DEBUG_FS
1787@@ -1182,6 +1217,7 @@
1788 #ifdef CONFIG_OF
1789 	dsi->bridge.of_node = pdev->dev.of_node;
1790 #endif
1791+	drm_bridge_add(&dsi->bridge);
1792
1793 	return dsi;
1794 }
1795diff -Naur a/drivers/gpu/drm/drm_aperture.c b/drivers/gpu/drm/drm_aperture.c
1796--- a/drivers/gpu/drm/drm_aperture.c	1970-01-01 08:00:00.000000000 +0800
1797+++ b/drivers/gpu/drm/drm_aperture.c	2023-02-23 17:02:04.951750958 +0800
1798@@ -0,0 +1,353 @@
1799+// SPDX-License-Identifier: MIT
1800+
1801+#include <linux/device.h>
1802+#include <linux/fb.h>
1803+#include <linux/list.h>
1804+#include <linux/mutex.h>
1805+#include <linux/pci.h>
1806+#include <linux/platform_device.h> /* for firmware helpers */
1807+#include <linux/slab.h>
1808+#include <linux/types.h>
1809+#include <linux/vgaarb.h>
1810+
1811+#include <drm/drm_aperture.h>
1812+#include <drm/drm_drv.h>
1813+#include <drm/drm_print.h>
1814+
1815+/**
1816+ * DOC: overview
1817+ *
1818+ * A graphics device might be supported by different drivers, but only one
1819+ * driver can be active at any given time. Many systems load a generic
1820+ * graphics drivers, such as EFI-GOP or VESA, early during the boot process.
1821+ * During later boot stages, they replace the generic driver with a dedicated,
1822+ * hardware-specific driver. To take over the device the dedicated driver
1823+ * first has to remove the generic driver. DRM aperture functions manage
1824+ * ownership of DRM framebuffer memory and hand-over between drivers.
1825+ *
1826+ * DRM drivers should call drm_aperture_remove_conflicting_framebuffers()
1827+ * at the top of their probe function. The function removes any generic
1828+ * driver that is currently associated with the given framebuffer memory.
1829+ * If the framebuffer is located at PCI BAR 0, the rsp code looks as in the
1830+ * example given below.
1831+ *
1832+ * .. code-block:: c
1833+ *
1834+ *	static const struct drm_driver example_driver = {
1835+ *		...
1836+ *	};
1837+ *
1838+ *	static int remove_conflicting_framebuffers(struct pci_dev *pdev)
1839+ *	{
1840+ *		bool primary = false;
1841+ *		resource_size_t base, size;
1842+ *		int ret;
1843+ *
1844+ *		base = pci_resource_start(pdev, 0);
1845+ *		size = pci_resource_len(pdev, 0);
1846+ *	#ifdef CONFIG_X86
1847+ *		primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
1848+ *	#endif
1849+ *
1850+ *		return drm_aperture_remove_conflicting_framebuffers(base, size, primary,
1851+ *		                                                    &example_driver);
1852+ *	}
1853+ *
1854+ *	static int probe(struct pci_dev *pdev)
1855+ *	{
1856+ *		int ret;
1857+ *
1858+ *		// Remove any generic drivers...
1859+ *		ret = remove_conflicting_framebuffers(pdev);
1860+ *		if (ret)
1861+ *			return ret;
1862+ *
1863+ *		// ... and initialize the hardware.
1864+ *		...
1865+ *
1866+ *		drm_dev_register();
1867+ *
1868+ *		return 0;
1869+ *	}
1870+ *
1871+ * PCI device drivers should call
1872+ * drm_aperture_remove_conflicting_pci_framebuffers() and let it detect the
1873+ * framebuffer apertures automatically. Device drivers without knowledge of
1874+ * the framebuffer's location shall call drm_aperture_remove_framebuffers(),
1875+ * which removes all drivers for known framebuffer.
1876+ *
1877+ * Drivers that are susceptible to being removed by other drivers, such as
1878+ * generic EFI or VESA drivers, have to register themselves as owners of their
1879+ * given framebuffer memory. Ownership of the framebuffer memory is achieved
1880+ * by calling devm_aperture_acquire_from_firmware(). On success, the driver
1881+ * is the owner of the framebuffer range. The function fails if the
1882+ * framebuffer is already by another driver. See below for an example.
1883+ *
1884+ * .. code-block:: c
1885+ *
1886+ *	static int acquire_framebuffers(struct drm_device *dev, struct platform_device *pdev)
1887+ *	{
1888+ *		resource_size_t base, size;
1889+ *
1890+ *		mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1891+ *		if (!mem)
1892+ *			return -EINVAL;
1893+ *		base = mem->start;
1894+ *		size = resource_size(mem);
1895+ *
1896+ *		return devm_acquire_aperture_from_firmware(dev, base, size);
1897+ *	}
1898+ *
1899+ *	static int probe(struct platform_device *pdev)
1900+ *	{
1901+ *		struct drm_device *dev;
1902+ *		int ret;
1903+ *
1904+ *		// ... Initialize the device...
1905+ *		dev = devm_drm_dev_alloc();
1906+ *		...
1907+ *
1908+ *		// ... and acquire ownership of the framebuffer.
1909+ *		ret = acquire_framebuffers(dev, pdev);
1910+ *		if (ret)
1911+ *			return ret;
1912+ *
1913+ *		drm_dev_register(dev, 0);
1914+ *
1915+ *		return 0;
1916+ *	}
1917+ *
1918+ * The generic driver is now subject to forced removal by other drivers. This
1919+ * only works for platform drivers that support hot unplug.
1920+ * When a driver calls drm_aperture_remove_conflicting_framebuffers() et al
1921+ * for the registered framebuffer range, the aperture helpers call
1922+ * platform_device_unregister() and the generic driver unloads itself. It
1923+ * may not access the device's registers, framebuffer memory, ROM, etc
1924+ * afterwards.
1925+ */
1926+
1927+struct drm_aperture {
1928+	struct drm_device *dev;
1929+	resource_size_t base;
1930+	resource_size_t size;
1931+	struct list_head lh;
1932+	void (*detach)(struct drm_device *dev);
1933+};
1934+
1935+static LIST_HEAD(drm_apertures);
1936+static DEFINE_MUTEX(drm_apertures_lock);
1937+
1938+static bool overlap(resource_size_t base1, resource_size_t end1,
1939+		    resource_size_t base2, resource_size_t end2)
1940+{
1941+	return (base1 < end2) && (end1 > base2);
1942+}
1943+
1944+static void devm_aperture_acquire_release(void *data)
1945+{
1946+	struct drm_aperture *ap = data;
1947+	bool detached = !ap->dev;
1948+
1949+	if (detached)
1950+		return;
1951+
1952+	mutex_lock(&drm_apertures_lock);
1953+	list_del(&ap->lh);
1954+	mutex_unlock(&drm_apertures_lock);
1955+}
1956+
1957+static int devm_aperture_acquire(struct drm_device *dev,
1958+				 resource_size_t base, resource_size_t size,
1959+				 void (*detach)(struct drm_device *))
1960+{
1961+	size_t end = base + size;
1962+	struct list_head *pos;
1963+	struct drm_aperture *ap;
1964+
1965+	mutex_lock(&drm_apertures_lock);
1966+
1967+	list_for_each(pos, &drm_apertures) {
1968+		ap = container_of(pos, struct drm_aperture, lh);
1969+		if (overlap(base, end, ap->base, ap->base + ap->size)) {
1970+			mutex_unlock(&drm_apertures_lock);
1971+			return -EBUSY;
1972+		}
1973+	}
1974+
1975+	ap = devm_kzalloc(dev->dev, sizeof(*ap), GFP_KERNEL);
1976+	if (!ap) {
1977+		mutex_unlock(&drm_apertures_lock);
1978+		return -ENOMEM;
1979+	}
1980+
1981+	ap->dev = dev;
1982+	ap->base = base;
1983+	ap->size = size;
1984+	ap->detach = detach;
1985+	INIT_LIST_HEAD(&ap->lh);
1986+
1987+	list_add(&ap->lh, &drm_apertures);
1988+
1989+	mutex_unlock(&drm_apertures_lock);
1990+
1991+	return devm_add_action_or_reset(dev->dev, devm_aperture_acquire_release, ap);
1992+}
1993+
1994+static void drm_aperture_detach_firmware(struct drm_device *dev)
1995+{
1996+	struct platform_device *pdev = to_platform_device(dev->dev);
1997+
1998+	/*
1999+	 * Remove the device from the device hierarchy. This is the right thing
2000+	 * to do for firmware-based DRM drivers, such as EFI, VESA or VGA. After
2001+	 * the new driver takes over the hardware, the firmware device's state
2002+	 * will be lost.
2003+	 *
2004+	 * For non-platform devices, a new callback would be required.
2005+	 *
2006+	 * If the aperture helpers ever need to handle native drivers, this call
2007+	 * would only have to unplug the DRM device, so that the hardware device
2008+	 * stays around after detachment.
2009+	 */
2010+	platform_device_unregister(pdev);
2011+}
2012+
2013+/**
2014+ * devm_aperture_acquire_from_firmware - Acquires ownership of a firmware framebuffer
2015+ *                                       on behalf of a DRM driver.
2016+ * @dev:	the DRM device to own the framebuffer memory
2017+ * @base:	the framebuffer's byte offset in physical memory
2018+ * @size:	the framebuffer size in bytes
2019+ *
2020+ * Installs the given device as the new owner of the framebuffer. The function
2021+ * expects the framebuffer to be provided by a platform device that has been
2022+ * set up by firmware. Firmware can be any generic interface, such as EFI,
2023+ * VESA, VGA, etc. If the native hardware driver takes over ownership of the
2024+ * framebuffer range, the firmware state gets lost. Aperture helpers will then
2025+ * unregister the platform device automatically. Acquired apertures are
2026+ * released automatically if the underlying device goes away.
2027+ *
2028+ * The function fails if the framebuffer range, or parts of it, is currently
2029+ * owned by another driver. To evict current owners, callers should use
2030+ * drm_aperture_remove_conflicting_framebuffers() et al. before calling this
2031+ * function. The function also fails if the given device is not a platform
2032+ * device.
2033+ *
2034+ * Returns:
2035+ * 0 on success, or a negative errno value otherwise.
2036+ */
2037+int devm_aperture_acquire_from_firmware(struct drm_device *dev, resource_size_t base,
2038+					resource_size_t size)
2039+{
2040+	if (drm_WARN_ON(dev, !dev_is_platform(dev->dev)))
2041+		return -EINVAL;
2042+
2043+	return devm_aperture_acquire(dev, base, size, drm_aperture_detach_firmware);
2044+}
2045+EXPORT_SYMBOL(devm_aperture_acquire_from_firmware);
2046+
2047+static void drm_aperture_detach_drivers(resource_size_t base, resource_size_t size)
2048+{
2049+	resource_size_t end = base + size;
2050+	struct list_head *pos, *n;
2051+
2052+	mutex_lock(&drm_apertures_lock);
2053+
2054+	list_for_each_safe(pos, n, &drm_apertures) {
2055+		struct drm_aperture *ap =
2056+			container_of(pos, struct drm_aperture, lh);
2057+		struct drm_device *dev = ap->dev;
2058+
2059+		if (WARN_ON_ONCE(!dev))
2060+			continue;
2061+
2062+		if (!overlap(base, end, ap->base, ap->base + ap->size))
2063+			continue;
2064+
2065+		ap->dev = NULL; /* detach from device */
2066+		list_del(&ap->lh);
2067+
2068+		ap->detach(dev);
2069+	}
2070+
2071+	mutex_unlock(&drm_apertures_lock);
2072+}
2073+
2074+/**
2075+ * drm_aperture_remove_conflicting_framebuffers - remove existing framebuffers in the given range
2076+ * @base: the aperture's base address in physical memory
2077+ * @size: aperture size in bytes
2078+ * @primary: also kick vga16fb if present
2079+ * @req_driver: requesting DRM driver
2080+ *
2081+ * This function removes graphics device drivers which use memory range described by
2082+ * @base and @size.
2083+ *
2084+ * Returns:
2085+ * 0 on success, or a negative errno code otherwise
2086+ */
2087+int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
2088+						 bool primary, const struct drm_driver *req_driver)
2089+{
2090+#if IS_REACHABLE(CONFIG_FB)
2091+	struct apertures_struct *a;
2092+	int ret;
2093+
2094+	a = alloc_apertures(1);
2095+	if (!a)
2096+		return -ENOMEM;
2097+
2098+	a->ranges[0].base = base;
2099+	a->ranges[0].size = size;
2100+
2101+	ret = remove_conflicting_framebuffers(a, req_driver->name, primary);
2102+	kfree(a);
2103+
2104+	if (ret)
2105+		return ret;
2106+#endif
2107+
2108+	drm_aperture_detach_drivers(base, size);
2109+
2110+	return 0;
2111+}
2112+EXPORT_SYMBOL(drm_aperture_remove_conflicting_framebuffers);
2113+
2114+/**
2115+ * drm_aperture_remove_conflicting_pci_framebuffers - remove existing framebuffers for PCI devices
2116+ * @pdev: PCI device
2117+ * @req_driver: requesting DRM driver
2118+ *
2119+ * This function removes graphics device drivers using memory range configured
2120+ * for any of @pdev's memory bars. The function assumes that PCI device with
2121+ * shadowed ROM drives a primary display and so kicks out vga16fb.
2122+ *
2123+ * Returns:
2124+ * 0 on success, or a negative errno code otherwise
2125+ */
2126+int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
2127+						     const struct drm_driver *req_driver)
2128+{
2129+	resource_size_t base, size;
2130+	int bar, ret = 0;
2131+
2132+	for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
2133+		if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
2134+			continue;
2135+		base = pci_resource_start(pdev, bar);
2136+		size = pci_resource_len(pdev, bar);
2137+		drm_aperture_detach_drivers(base, size);
2138+	}
2139+
2140+	/*
2141+	 * WARNING: Apparently we must kick fbdev drivers before vgacon,
2142+	 * otherwise the vga fbdev driver falls over.
2143+	 */
2144+#if IS_REACHABLE(CONFIG_FB)
2145+	ret = remove_conflicting_pci_framebuffers(pdev, req_driver->name);
2146+#endif
2147+	if (ret == 0)
2148+		ret = vga_remove_vgacon(pdev);
2149+	return ret;
2150+}
2151+EXPORT_SYMBOL(drm_aperture_remove_conflicting_pci_framebuffers);
2152diff -Naur a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
2153--- a/drivers/gpu/drm/drm_connector.c	2022-12-19 17:13:12.593517982 +0800
2154+++ b/drivers/gpu/drm/drm_connector.c	2023-02-23 17:02:04.951750958 +0800
2155@@ -2144,6 +2144,55 @@
2156 EXPORT_SYMBOL(drm_connector_attach_max_bpc_property);
2157
2158 /**
2159+ * drm_connector_attach_hdr_output_metadata_property - attach "HDR_OUTPUT_METADA" property
2160+ * @connector: connector to attach the property on.
2161+ *
2162+ * This is used to allow the userspace to send HDR Metadata to the
2163+ * driver.
2164+ *
2165+ * Returns:
2166+ * Zero on success, negative errno on failure.
2167+ */
2168+int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector)
2169+{
2170+	struct drm_device *dev = connector->dev;
2171+	struct drm_property *prop = dev->mode_config.hdr_output_metadata_property;
2172+
2173+	drm_object_attach_property(&connector->base, prop, 0);
2174+
2175+	return 0;
2176+}
2177+EXPORT_SYMBOL(drm_connector_attach_hdr_output_metadata_property);
2178+
2179+/**
2180+ * drm_connector_atomic_hdr_metadata_equal - checks if the hdr metadata changed
2181+ * @old_state: old connector state to compare
2182+ * @new_state: new connector state to compare
2183+ *
2184+ * This is used by HDR-enabled drivers to test whether the HDR metadata
2185+ * have changed between two different connector state (and thus probably
2186+ * requires a full blown mode change).
2187+ *
2188+ * Returns:
2189+ * True if the metadata are equal, False otherwise
2190+ */
2191+bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,
2192+					     struct drm_connector_state *new_state)
2193+{
2194+	struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
2195+	struct drm_property_blob *new_blob = new_state->hdr_output_metadata;
2196+
2197+	if (!old_blob || !new_blob)
2198+		return old_blob == new_blob;
2199+
2200+	if (old_blob->length != new_blob->length)
2201+		return false;
2202+
2203+	return !memcmp(old_blob->data, new_blob->data, old_blob->length);
2204+}
2205+EXPORT_SYMBOL(drm_connector_atomic_hdr_metadata_equal);
2206+
2207+/**
2208  * drm_connector_set_vrr_capable_property - sets the variable refresh rate
2209  * capable property for a connector
2210  * @connector: drm connector
2211diff -Naur a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
2212--- a/drivers/gpu/drm/drm_ioctl.c	2022-12-19 17:13:12.597518030 +0800
2213+++ b/drivers/gpu/drm/drm_ioctl.c	2023-02-23 17:02:04.955751014 +0800
2214@@ -678,9 +678,9 @@
2215 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0),
2216 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER),
2217 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER),
2218-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0),
2219-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0),
2220-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 0),
2221+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_RENDER_ALLOW),
2222+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_RENDER_ALLOW),
2223+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_RENDER_ALLOW),
2224 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, 0),
2225 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER),
2226 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER),
2227diff -Naur a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
2228--- a/drivers/gpu/drm/drm_plane_helper.c	2022-12-19 17:13:12.601518079 +0800
2229+++ b/drivers/gpu/drm/drm_plane_helper.c	2023-02-23 17:02:04.955751014 +0800
2230@@ -123,6 +123,7 @@
2231 		.crtc_w = drm_rect_width(dst),
2232 		.crtc_h = drm_rect_height(dst),
2233 		.rotation = rotation,
2234+		.visible = *visible,
2235 	};
2236 	struct drm_crtc_state crtc_state = {
2237 		.crtc = crtc,
2238diff -Naur a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
2239--- a/drivers/gpu/drm/drm_vblank.c	2022-12-19 17:13:12.601518079 +0800
2240+++ b/drivers/gpu/drm/drm_vblank.c	2023-02-23 17:02:04.955751014 +0800
2241@@ -1725,6 +1725,15 @@
2242 	reply->tval_usec = ts.tv_nsec / 1000;
2243 }
2244
2245+static bool drm_wait_vblank_supported(struct drm_device *dev)
2246+{
2247+#if IS_ENABLED(CONFIG_DRM_LEGACY)
2248+	if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY)))
2249+		return dev->irq_enabled;
2250+#endif
2251+	return drm_dev_has_vblank(dev);
2252+}
2253+
2254 int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
2255 			  struct drm_file *file_priv)
2256 {
2257@@ -1736,7 +1745,7 @@
2258 	unsigned int pipe_index;
2259 	unsigned int flags, pipe, high_pipe;
2260
2261-	if (!dev->irq_enabled)
2262+	if (!drm_wait_vblank_supported(dev))
2263 		return -EOPNOTSUPP;
2264
2265 	if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
2266@@ -2011,7 +2020,7 @@
2267 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2268 		return -EOPNOTSUPP;
2269
2270-	if (!dev->irq_enabled)
2271+	if (!drm_dev_has_vblank(dev))
2272 		return -EOPNOTSUPP;
2273
2274 	crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id);
2275@@ -2070,7 +2079,7 @@
2276 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2277 		return -EOPNOTSUPP;
2278
2279-	if (!dev->irq_enabled)
2280+	if (!drm_dev_has_vblank(dev))
2281 		return -EOPNOTSUPP;
2282
2283 	crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id);
2284diff -Naur a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
2285--- a/drivers/gpu/drm/Makefile	2022-12-19 17:13:11.981510649 +0800
2286+++ b/drivers/gpu/drm/Makefile	2023-02-23 17:02:04.955751014 +0800
2287@@ -18,7 +18,7 @@
2288 		drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
2289 		drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
2290 		drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
2291-		drm_managed.o drm_vblank_work.o
2292+		drm_managed.o drm_vblank_work.o drm_aperture.o
2293
2294 drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
2295 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
2296diff -Naur a/drivers/gpu/drm/meson/Kconfig b/drivers/gpu/drm/meson/Kconfig
2297--- a/drivers/gpu/drm/meson/Kconfig	2022-12-19 17:13:12.677518989 +0800
2298+++ b/drivers/gpu/drm/meson/Kconfig	2023-02-23 17:02:04.955751014 +0800
2299@@ -6,9 +6,11 @@
2300 	select DRM_KMS_HELPER
2301 	select DRM_KMS_CMA_HELPER
2302 	select DRM_GEM_CMA_HELPER
2303+	select DRM_DISPLAY_CONNECTOR
2304 	select VIDEOMODE_HELPERS
2305 	select REGMAP_MMIO
2306 	select MESON_CANVAS
2307+	select CEC_CORE if CEC_NOTIFIER
2308
2309 config DRM_MESON_DW_HDMI
2310 	tristate "HDMI Synopsys Controller support for Amlogic Meson Display"
2311@@ -16,3 +18,10 @@
2312 	default y if DRM_MESON
2313 	select DRM_DW_HDMI
2314 	imply DRM_DW_HDMI_I2S_AUDIO
2315+
2316+config DRM_MESON_DW_MIPI_DSI
2317+	tristate "MIPI DSI Synopsys Controller support for Amlogic Meson Display"
2318+	depends on DRM_MESON
2319+	default y if DRM_MESON
2320+	select DRM_DW_MIPI_DSI
2321+	select GENERIC_PHY_MIPI_DPHY
2322diff -Naur a/drivers/gpu/drm/meson/Makefile b/drivers/gpu/drm/meson/Makefile
2323--- a/drivers/gpu/drm/meson/Makefile	2022-12-19 17:13:12.677518989 +0800
2324+++ b/drivers/gpu/drm/meson/Makefile	2023-02-23 17:02:04.955751014 +0800
2325@@ -1,7 +1,9 @@
2326 # SPDX-License-Identifier: GPL-2.0-only
2327-meson-drm-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
2328+meson-drm-y := meson_drv.o meson_plane.o meson_cursor.o meson_crtc.o meson_encoder_cvbs.o
2329 meson-drm-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_overlay.o
2330 meson-drm-y += meson_rdma.o meson_osd_afbcd.o
2331+meson-drm-y += meson_encoder_hdmi.o meson_encoder_dsi.o
2332
2333 obj-$(CONFIG_DRM_MESON) += meson-drm.o
2334 obj-$(CONFIG_DRM_MESON_DW_HDMI) += meson_dw_hdmi.o
2335+obj-$(CONFIG_DRM_MESON_DW_MIPI_DSI) += meson_dw_mipi_dsi.o
2336diff -Naur a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c
2337--- a/drivers/gpu/drm/meson/meson_crtc.c	2022-12-19 17:13:12.677518989 +0800
2338+++ b/drivers/gpu/drm/meson/meson_crtc.c	2023-02-23 17:02:04.955751014 +0800
2339@@ -36,6 +36,7 @@
2340 	struct drm_pending_vblank_event *event;
2341 	struct meson_drm *priv;
2342 	void (*enable_osd1)(struct meson_drm *priv);
2343+	void (*enable_osd2)(struct meson_drm *priv);
2344 	void (*enable_vd1)(struct meson_drm *priv);
2345 	void (*enable_osd1_afbc)(struct meson_drm *priv);
2346 	void (*disable_osd1_afbc)(struct meson_drm *priv);
2347@@ -45,6 +46,10 @@
2348 };
2349 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
2350
2351+static bool s_force_commit = false;
2352+static bool s_force_osd1_disable = false;
2353+static bool s_force_video_zorder_up = false;
2354+
2355 /* CRTC */
2356
2357 static int meson_crtc_enable_vblank(struct drm_crtc *crtc)
2358@@ -81,8 +86,11 @@
2359
2360 };
2361
2362+struct drm_display_mode meson_display_mode = { 0 };
2363+EXPORT_SYMBOL(meson_display_mode);
2364+
2365 static void meson_g12a_crtc_atomic_enable(struct drm_crtc *crtc,
2366-					  struct drm_crtc_state *old_state)
2367+					  struct drm_crtc_state *old_crtc_state)
2368 {
2369 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
2370 	struct drm_crtc_state *crtc_state = crtc->state;
2371@@ -110,15 +118,31 @@
2372 	writel_relaxed(0 << 16 |
2373 			(crtc_state->mode.vdisplay - 1),
2374 			priv->io_base + _REG(VPP_OSD1_BLD_V_SCOPE));
2375+	writel_relaxed(0 << 16 |
2376+			(crtc_state->mode.hdisplay - 1),
2377+			priv->io_base + _REG(VPP_OSD2_BLD_H_SCOPE));
2378+	writel_relaxed(0 << 16 |
2379+			(crtc_state->mode.vdisplay - 1),
2380+			priv->io_base + _REG(VPP_OSD2_BLD_V_SCOPE));
2381+	writel_relaxed(crtc_state->mode.hdisplay |
2382+			crtc_state->mode.vdisplay << 16,
2383+		       priv->io_base +
2384+		       _REG(VIU_OSD_BLEND_BLEND0_SIZE));
2385+	writel_relaxed(crtc_state->mode.hdisplay |
2386+			crtc_state->mode.vdisplay << 16,
2387+		       priv->io_base +
2388+		       _REG(VIU_OSD_BLEND_BLEND1_SIZE));
2389 	writel_relaxed(crtc_state->mode.hdisplay << 16 |
2390 			crtc_state->mode.vdisplay,
2391 			priv->io_base + _REG(VPP_OUT_H_V_SIZE));
2392
2393 	drm_crtc_vblank_on(crtc);
2394+
2395+	memcpy(&meson_display_mode, &crtc_state->mode, sizeof(meson_display_mode));
2396 }
2397
2398 static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
2399-				     struct drm_crtc_state *old_state)
2400+				     struct drm_crtc_state *old_crtc_state)
2401 {
2402 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
2403 	struct drm_crtc_state *crtc_state = crtc->state;
2404@@ -146,7 +170,7 @@
2405 }
2406
2407 static void meson_g12a_crtc_atomic_disable(struct drm_crtc *crtc,
2408-					   struct drm_crtc_state *old_state)
2409+					   struct drm_crtc_state *old_crtc_state)
2410 {
2411 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
2412 	struct meson_drm *priv = meson_crtc->priv;
2413@@ -158,6 +182,9 @@
2414 	priv->viu.osd1_enabled = false;
2415 	priv->viu.osd1_commit = false;
2416
2417+	priv->viu.osd2_enabled = false;
2418+	priv->viu.osd2_commit = false;
2419+
2420 	priv->viu.vd1_enabled = false;
2421 	priv->viu.vd1_commit = false;
2422
2423@@ -171,7 +198,7 @@
2424 }
2425
2426 static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
2427-				      struct drm_crtc_state *old_state)
2428+				      struct drm_crtc_state *old_crtc_state)
2429 {
2430 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
2431 	struct meson_drm *priv = meson_crtc->priv;
2432@@ -183,11 +210,14 @@
2433 	priv->viu.osd1_enabled = false;
2434 	priv->viu.osd1_commit = false;
2435
2436+	priv->viu.osd2_enabled = false;
2437+	priv->viu.osd2_commit = false;
2438+
2439 	priv->viu.vd1_enabled = false;
2440 	priv->viu.vd1_commit = false;
2441
2442 	/* Disable VPP Postblend */
2443-	writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_VD1_POSTBLEND |
2444+	writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND | VPP_VD1_POSTBLEND |
2445 			    VPP_VD1_PREBLEND | VPP_POSTBLEND_ENABLE, 0,
2446 			    priv->io_base + _REG(VPP_MISC));
2447
2448@@ -201,7 +231,7 @@
2449 }
2450
2451 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
2452-				    struct drm_crtc_state *state)
2453+				    struct drm_crtc_state *old_crtc_state)
2454 {
2455 	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
2456 	unsigned long flags;
2457@@ -223,6 +253,7 @@
2458 	struct meson_drm *priv = meson_crtc->priv;
2459
2460 	priv->viu.osd1_commit = true;
2461+	priv->viu.osd2_commit = true;
2462 	priv->viu.vd1_commit = true;
2463 }
2464
2465@@ -246,6 +277,12 @@
2466 			    priv->io_base + _REG(VPP_MISC));
2467 }
2468
2469+static void meson_crtc_enable_osd2(struct meson_drm *priv)
2470+{
2471+	writel_bits_relaxed(VPP_OSD2_POSTBLEND, VPP_OSD2_POSTBLEND,
2472+			    priv->io_base + _REG(VPP_MISC));
2473+}
2474+
2475 static void meson_crtc_g12a_enable_osd1_afbc(struct meson_drm *priv)
2476 {
2477 	writel_relaxed(priv->viu.osd1_blk2_cfg4,
2478@@ -274,14 +311,25 @@
2479 	writel_relaxed(priv->viu.osd_blend_din0_scope_v,
2480 		       priv->io_base +
2481 		       _REG(VIU_OSD_BLEND_DIN0_SCOPE_V));
2482-	writel_relaxed(priv->viu.osb_blend0_size,
2483+	if (s_force_video_zorder_up) {
2484+		writel_bits_relaxed(0xF << 8, OSD_BLEND_POSTBLD_SRC_VD1,
2485+				priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
2486+	} else {
2487+		writel_bits_relaxed(OSD_BLEND_POSTBLD_SRC_OSD1, OSD_BLEND_POSTBLD_SRC_OSD1,
2488+				priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
2489+	}
2490+}
2491+
2492+static void meson_g12a_crtc_enable_osd2(struct meson_drm *priv)
2493+{
2494+	writel_relaxed(priv->viu.osd_blend_din3_scope_h,
2495 		       priv->io_base +
2496-		       _REG(VIU_OSD_BLEND_BLEND0_SIZE));
2497-	writel_relaxed(priv->viu.osb_blend1_size,
2498+		       _REG(VIU_OSD_BLEND_DIN1_SCOPE_H));
2499+	writel_relaxed(priv->viu.osd_blend_din3_scope_v,
2500 		       priv->io_base +
2501-		       _REG(VIU_OSD_BLEND_BLEND1_SIZE));
2502-	writel_bits_relaxed(3 << 8, 3 << 8,
2503-			    priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
2504+		       _REG(VIU_OSD_BLEND_DIN1_SCOPE_V));
2505+	writel_bits_relaxed(OSD_BLEND_POSTBLD_SRC_OSD2, OSD_BLEND_POSTBLD_SRC_OSD2,
2506+			    priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
2507 }
2508
2509 static void meson_crtc_enable_vd1(struct meson_drm *priv)
2510@@ -315,8 +363,22 @@
2511 	struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
2512 	unsigned long flags;
2513
2514+	if (s_force_commit) {
2515+		s_force_commit = false;
2516+		priv->viu.osd1_commit = true;
2517+		if (s_force_osd1_disable) {
2518+			writel_bits_relaxed(OSD_BLEND_POSTBLD_SRC_OSD1, 0,
2519+					priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
2520+		} else if (s_force_video_zorder_up) {
2521+			writel_bits_relaxed(0xF << 8, OSD_BLEND_POSTBLD_SRC_VD1,
2522+					priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); // OSD1 postblend src -> vd1
2523+			writel_bits_relaxed(0xF << 8, OSD_BLEND_POSTBLD_SRC_OSD1,
2524+					priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); // VD1 postblend src -> osd1
2525+		}
2526+	}
2527+
2528 	/* Update the OSD registers */
2529-	if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
2530+	if (!s_force_osd1_disable && priv->viu.osd1_enabled && priv->viu.osd1_commit) {
2531 		writel_relaxed(priv->viu.osd1_ctrl_stat,
2532 				priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
2533 		writel_relaxed(priv->viu.osd1_ctrl_stat2,
2534@@ -388,6 +450,43 @@
2535 		priv->viu.osd1_commit = false;
2536 	}
2537
2538+	if (priv->viu.osd2_enabled && priv->viu.osd2_commit) {
2539+		writel_relaxed(priv->viu.osd2_ctrl_stat,
2540+				priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
2541+		writel_relaxed(priv->viu.osd2_ctrl_stat2,
2542+				priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
2543+		writel_relaxed(priv->viu.osd2_blk0_cfg[0],
2544+				priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W0));
2545+		writel_relaxed(priv->viu.osd2_blk0_cfg[1],
2546+				priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W1));
2547+		writel_relaxed(priv->viu.osd2_blk0_cfg[2],
2548+				priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W2));
2549+		writel_relaxed(priv->viu.osd2_blk0_cfg[3],
2550+				priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W3));
2551+		writel_relaxed(priv->viu.osd2_blk0_cfg[4],
2552+				priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W4));
2553+
2554+		/* vsync forced to update INTERLACE_SEL_ODD in interlace mode */
2555+		meson_crtc->vsync_forced = priv->viu.osd2_interlace;
2556+
2557+		meson_canvas_config(priv->canvas, priv->canvas_id_osd2,
2558+				priv->viu.osd2_addr,
2559+				priv->viu.osd2_stride,
2560+				priv->viu.osd2_height,
2561+				MESON_CANVAS_WRAP_NONE,
2562+				MESON_CANVAS_BLKMODE_LINEAR, 0);
2563+
2564+		/* Enable OSD2 */
2565+		if (meson_crtc->enable_osd2)
2566+			meson_crtc->enable_osd2(priv);
2567+
2568+		priv->viu.osd2_commit = false;
2569+	} else if (priv->viu.osd2_enabled && priv->viu.osd2_interlace) {
2570+		u32 reg = readl_relaxed(priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W0)) & ~BIT(0);
2571+		writel_relaxed(reg | meson_venci_get_field(priv) ? 1 : 0,
2572+				priv->io_base + _REG(VIU_OSD2_BLK0_CFG_W0));
2573+	}
2574+
2575 	/* Update the VD1 registers */
2576 	if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
2577
2578@@ -671,12 +770,77 @@
2579 	spin_unlock_irqrestore(&priv->drm->event_lock, flags);
2580 }
2581
2582+static ssize_t enable_osd_store(struct class *class,
2583+		struct class_attribute *attr,
2584+		const char *buf, size_t count)
2585+{
2586+	pr_info("enable_osd_store: %s\n", buf);
2587+	int osd1_enabled = 1;
2588+	if (1 != sscanf(buf, "%d", &osd1_enabled)) {
2589+		return 0;
2590+	}
2591+	s_force_osd1_disable = !osd1_enabled;
2592+	s_force_commit = true;
2593+	pr_info("s_force_osd1_disable=%d\n", s_force_osd1_disable);
2594+	return count;
2595+}
2596+
2597+static ssize_t enable_osd_show(struct class *class,
2598+		struct class_attribute *attr,
2599+		char *buf)
2600+{
2601+	return sprintf(buf, "%d\n", s_force_osd1_disable ? 0 : 1);
2602+}
2603+
2604+static ssize_t video_zorder_up_store(struct class *class,
2605+		struct class_attribute *attr,
2606+		const char *buf, size_t count)
2607+{
2608+	pr_info("enable_osd_store: %s\n", buf);
2609+	int video_zorder_up = 0;
2610+	if (1 != sscanf(buf, "%d", &video_zorder_up)) {
2611+		return 0;
2612+	}
2613+	s_force_video_zorder_up = video_zorder_up;
2614+	s_force_commit = true;
2615+	pr_info("s_force_video_zorder_up=%d\n", s_force_video_zorder_up);
2616+	return count;
2617+}
2618+
2619+static ssize_t video_zorder_up_show(struct class *class,
2620+		struct class_attribute *attr,
2621+		char *buf)
2622+{
2623+	return sprintf(buf, "%d\n", s_force_video_zorder_up ? 1 : 0);
2624+}
2625+
2626+static CLASS_ATTR_RW(enable_osd);
2627+static CLASS_ATTR_RW(video_zorder_up);
2628+
2629+
2630+static struct attribute *meson_crtc_class_attrs[] = {
2631+	&class_attr_enable_osd.attr,
2632+	&class_attr_video_zorder_up.attr,
2633+	NULL
2634+};
2635+
2636+ATTRIBUTE_GROUPS(meson_crtc_class);
2637+static struct class meson_crtc_class = {
2638+	.name = "meson_crtc",
2639+	.class_groups = meson_crtc_class_groups,
2640+};
2641+
2642+
2643 int meson_crtc_create(struct meson_drm *priv)
2644 {
2645 	struct meson_crtc *meson_crtc;
2646 	struct drm_crtc *crtc;
2647 	int ret;
2648
2649+	ret = class_register(&meson_crtc_class);
2650+	if (ret < 0)
2651+		return ret;
2652+
2653 	meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
2654 				  GFP_KERNEL);
2655 	if (!meson_crtc)
2656@@ -685,7 +849,7 @@
2657 	meson_crtc->priv = priv;
2658 	crtc = &meson_crtc->base;
2659 	ret = drm_crtc_init_with_planes(priv->drm, crtc,
2660-					priv->primary_plane, NULL,
2661+					priv->primary_plane, priv->cursor_plane,
2662 					&meson_crtc_funcs, "meson_crtc");
2663 	if (ret) {
2664 		dev_err(priv->drm->dev, "Failed to init CRTC\n");
2665@@ -694,6 +858,7 @@
2666
2667 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
2668 		meson_crtc->enable_osd1 = meson_g12a_crtc_enable_osd1;
2669+		meson_crtc->enable_osd2 = meson_g12a_crtc_enable_osd2;
2670 		meson_crtc->enable_vd1 = meson_g12a_crtc_enable_vd1;
2671 		meson_crtc->viu_offset = MESON_G12A_VIU_OFFSET;
2672 		meson_crtc->enable_osd1_afbc =
2673@@ -703,6 +868,7 @@
2674 		drm_crtc_helper_add(crtc, &meson_g12a_crtc_helper_funcs);
2675 	} else {
2676 		meson_crtc->enable_osd1 = meson_crtc_enable_osd1;
2677+		meson_crtc->enable_osd2 = meson_crtc_enable_osd2;
2678 		meson_crtc->enable_vd1 = meson_crtc_enable_vd1;
2679 		if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
2680 			meson_crtc->enable_osd1_afbc =
2681diff -Naur a/drivers/gpu/drm/meson/meson_cursor.c b/drivers/gpu/drm/meson/meson_cursor.c
2682--- a/drivers/gpu/drm/meson/meson_cursor.c	1970-01-01 08:00:00.000000000 +0800
2683+++ b/drivers/gpu/drm/meson/meson_cursor.c	2023-02-23 17:02:04.955751014 +0800
2684@@ -0,0 +1,244 @@
2685+// SPDX-License-Identifier: GPL-2.0-or-later
2686+/*
2687+ * Copyright (C) 2021 BayLibre, SAS
2688+ * Author: Neil Armstrong <narmstrong@baylibre.com>
2689+ */
2690+
2691+#include <linux/bitfield.h>
2692+
2693+#include <drm/drm_atomic.h>
2694+#include <drm/drm_atomic_helper.h>
2695+#include <drm/drm_device.h>
2696+#include <drm/drm_fb_cma_helper.h>
2697+#include <drm/drm_fourcc.h>
2698+#include <drm/drm_gem_cma_helper.h>
2699+#include <drm/drm_gem_framebuffer_helper.h>
2700+#include <drm/drm_plane_helper.h>
2701+
2702+#include "meson_cursor.h"
2703+#include "meson_registers.h"
2704+#include "meson_viu.h"
2705+
2706+struct meson_cursor {
2707+	struct drm_plane base;
2708+	struct meson_drm *priv;
2709+};
2710+#define to_meson_cursor(x) container_of(x, struct meson_cursor, base)
2711+
2712+static int meson_cursor_atomic_check(struct drm_plane *plane,
2713+				    struct drm_plane_state *state)
2714+{
2715+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state->state,
2716+										 plane);
2717+	struct drm_crtc_state *crtc_state;
2718+
2719+	if (!new_plane_state->crtc)
2720+		return 0;
2721+
2722+	crtc_state = drm_atomic_get_crtc_state(state->state,
2723+					       new_plane_state->crtc);
2724+	if (IS_ERR(crtc_state))
2725+		return PTR_ERR(crtc_state);
2726+
2727+	return drm_atomic_helper_check_plane_state(new_plane_state,
2728+						   crtc_state,
2729+						   DRM_PLANE_HELPER_NO_SCALING,
2730+						   DRM_PLANE_HELPER_NO_SCALING,
2731+						   true, true);
2732+}
2733+
2734+/* Takes a fixed 16.16 number and converts it to integer. */
2735+static inline int64_t fixed16_to_int(int64_t value)
2736+{
2737+	return value >> 16;
2738+}
2739+
2740+static void meson_cursor_atomic_update(struct drm_plane *plane,
2741+				      struct drm_plane_state *state)
2742+{
2743+	struct meson_cursor *meson_cursor = to_meson_cursor(plane);
2744+	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state->state,
2745+									   plane);
2746+	struct drm_rect dest = drm_plane_state_dest(new_state);
2747+	struct meson_drm *priv = meson_cursor->priv;
2748+	struct drm_framebuffer *fb = new_state->fb;
2749+	struct drm_gem_cma_object *gem;
2750+	unsigned long flags;
2751+	int dst_w, dst_h;
2752+
2753+	/*
2754+	 * Update Coordinates
2755+	 * Update Formats
2756+	 * Update Buffer
2757+	 * Enable Plane
2758+	 */
2759+	spin_lock_irqsave(&priv->drm->event_lock, flags);
2760+
2761+	/* Enable OSD and BLK0, set max global alpha */
2762+	priv->viu.osd2_ctrl_stat = OSD_ENABLE |
2763+				   (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
2764+				   OSD_BLK0_ENABLE;
2765+
2766+	priv->viu.osd2_ctrl_stat2 = readl(priv->io_base +
2767+					  _REG(VIU_OSD2_CTRL_STAT2));
2768+
2769+	/* Set up BLK0 to point to the right canvas */
2770+	priv->viu.osd2_blk0_cfg[0] = priv->canvas_id_osd2 << OSD_CANVAS_SEL;
2771+	priv->viu.osd2_blk0_cfg[0] |= OSD_ENDIANNESS_LE;
2772+
2773+	/* On GXBB, Use the old non-HDR RGB2YUV converter */
2774+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
2775+		priv->viu.osd2_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
2776+
2777+	switch (fb->format->format) {
2778+	case DRM_FORMAT_XRGB8888:
2779+	case DRM_FORMAT_ARGB8888:
2780+		priv->viu.osd2_blk0_cfg[0] |= OSD_BLK_MODE_32 |
2781+			OSD_COLOR_MATRIX_32_ARGB;
2782+		break;
2783+	case DRM_FORMAT_XBGR8888:
2784+	case DRM_FORMAT_ABGR8888:
2785+		priv->viu.osd2_blk0_cfg[0] |= OSD_BLK_MODE_32 |
2786+			OSD_COLOR_MATRIX_32_ABGR;
2787+		break;
2788+	case DRM_FORMAT_RGB888:
2789+		priv->viu.osd2_blk0_cfg[0] |= OSD_BLK_MODE_24 |
2790+			OSD_COLOR_MATRIX_24_RGB;
2791+		break;
2792+	case DRM_FORMAT_RGB565:
2793+		priv->viu.osd2_blk0_cfg[0] |= OSD_BLK_MODE_16 |
2794+			OSD_COLOR_MATRIX_16_RGB565;
2795+		break;
2796+	}
2797+
2798+	switch (fb->format->format) {
2799+	case DRM_FORMAT_XRGB8888:
2800+	case DRM_FORMAT_XBGR8888:
2801+		/* For XRGB, replace the pixel's alpha by 0xFF */
2802+		priv->viu.osd2_ctrl_stat2 |= OSD_REPLACE_EN;
2803+		break;
2804+	case DRM_FORMAT_ARGB8888:
2805+	case DRM_FORMAT_ABGR8888:
2806+		/* For ARGB, use the pixel's alpha */
2807+		priv->viu.osd2_ctrl_stat2 &= ~OSD_REPLACE_EN;
2808+		break;
2809+	}
2810+
2811+	dst_w = new_state->crtc_w;
2812+	dst_h = new_state->crtc_h;
2813+
2814+	if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
2815+		priv->viu.osd2_interlace = true;
2816+	else
2817+		priv->viu.osd2_interlace = false;
2818+
2819+	/*
2820+	 * The format of these registers is (x2 << 16 | x1),
2821+	 * where x2 is exclusive.
2822+	 * e.g. +30x1920 would be (1919 << 16) | 30
2823+	 */
2824+	priv->viu.osd2_blk0_cfg[1] =
2825+				((fixed16_to_int(new_state->src.x2) - 1) << 16) |
2826+				fixed16_to_int(new_state->src.x1);
2827+	priv->viu.osd2_blk0_cfg[2] =
2828+				((fixed16_to_int(new_state->src.y2) - 1) << 16) |
2829+				fixed16_to_int(new_state->src.y1);
2830+	priv->viu.osd2_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
2831+	priv->viu.osd2_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
2832+
2833+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
2834+		priv->viu.osd_blend_din3_scope_h = ((dest.x2 - 1) << 16) | dest.x1;
2835+		priv->viu.osd_blend_din3_scope_v = ((dest.y2 - 1) << 16) | dest.y1;
2836+		priv->viu.osb_blend1_size = dst_h << 16 | dst_w;
2837+	}
2838+
2839+	/* Update Canvas with buffer address */
2840+	gem = drm_fb_cma_get_gem_obj(fb, 0);
2841+
2842+	priv->viu.osd2_addr = gem->paddr;
2843+	priv->viu.osd2_stride = fb->pitches[0];
2844+	priv->viu.osd2_height = fb->height;
2845+	priv->viu.osd2_width = fb->width;
2846+
2847+	/* TOFIX: Reset OSD2 before enabling it on GXL+ SoCs ? */
2848+
2849+	priv->viu.osd2_enabled = true;
2850+
2851+	spin_unlock_irqrestore(&priv->drm->event_lock, flags);
2852+}
2853+
2854+static void meson_cursor_atomic_disable(struct drm_plane *plane,
2855+				       struct drm_plane_state *state)
2856+{
2857+	struct meson_cursor *meson_cursor = to_meson_cursor(plane);
2858+	struct meson_drm *priv = meson_cursor->priv;
2859+
2860+	/* Disable OSD2 */
2861+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
2862+		writel_bits_relaxed(OSD_BLEND_POSTBLD_SRC_OSD2, 0,
2863+				    priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
2864+	else
2865+		writel_bits_relaxed(VPP_OSD2_POSTBLEND, 0,
2866+				    priv->io_base + _REG(VPP_MISC));
2867+
2868+	priv->viu.osd2_enabled = false;
2869+}
2870+
2871+static const struct drm_plane_helper_funcs meson_cursor_helper_funcs = {
2872+	.atomic_check	= meson_cursor_atomic_check,
2873+	.atomic_disable	= meson_cursor_atomic_disable,
2874+	.atomic_update	= meson_cursor_atomic_update,
2875+};
2876+
2877+static const struct drm_plane_funcs meson_cursor_funcs = {
2878+	.update_plane		= drm_atomic_helper_update_plane,
2879+	.disable_plane		= drm_atomic_helper_disable_plane,
2880+	.destroy		= drm_plane_cleanup,
2881+	.reset			= drm_atomic_helper_plane_reset,
2882+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
2883+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
2884+};
2885+
2886+static const uint32_t supported_drm_formats[] = {
2887+	DRM_FORMAT_ARGB8888,
2888+	DRM_FORMAT_ABGR8888,
2889+	DRM_FORMAT_XRGB8888,
2890+	DRM_FORMAT_XBGR8888,
2891+	DRM_FORMAT_RGB888,
2892+	DRM_FORMAT_RGB565,
2893+};
2894+
2895+static const uint64_t format_modifiers_default[] = {
2896+	DRM_FORMAT_MOD_LINEAR,
2897+	DRM_FORMAT_MOD_INVALID,
2898+};
2899+
2900+int meson_cursor_create(struct meson_drm *priv)
2901+{
2902+	struct meson_cursor *meson_cursor;
2903+	struct drm_plane *cursor;
2904+
2905+	meson_cursor = devm_kzalloc(priv->drm->dev, sizeof(*meson_cursor),
2906+				   GFP_KERNEL);
2907+	if (!meson_cursor)
2908+		return -ENOMEM;
2909+
2910+	meson_cursor->priv = priv;
2911+	cursor = &meson_cursor->base;
2912+
2913+	drm_universal_plane_init(priv->drm, cursor, 0xFF,
2914+				 &meson_cursor_funcs,
2915+				 supported_drm_formats,
2916+				 ARRAY_SIZE(supported_drm_formats),
2917+				 format_modifiers_default,
2918+				 DRM_PLANE_TYPE_CURSOR, "meson_cursor_plane");
2919+
2920+	drm_plane_helper_add(cursor, &meson_cursor_helper_funcs);
2921+
2922+	/* For now, OSD Cursor is always on top of the primary plane */
2923+	drm_plane_create_zpos_immutable_property(cursor, 2);
2924+
2925+	priv->cursor_plane = cursor;
2926+
2927+	return 0;
2928+}
2929diff -Naur a/drivers/gpu/drm/meson/meson_cursor.h b/drivers/gpu/drm/meson/meson_cursor.h
2930--- a/drivers/gpu/drm/meson/meson_cursor.h	1970-01-01 08:00:00.000000000 +0800
2931+++ b/drivers/gpu/drm/meson/meson_cursor.h	2023-02-23 17:02:04.955751014 +0800
2932@@ -0,0 +1,14 @@
2933+/* SPDX-License-Identifier: GPL-2.0-or-later */
2934+/*
2935+ * Copyright (C) 2021 BayLibre, SAS
2936+ * Author: Neil Armstrong <narmstrong@baylibre.com>
2937+ */
2938+
2939+#ifndef __MESON_CURSOR_H
2940+#define __MESON_CURSOR_H
2941+
2942+#include "meson_drv.h"
2943+
2944+int meson_cursor_create(struct meson_drm *priv);
2945+
2946+#endif /* __MESON_CURSOR_H */
2947diff -Naur a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
2948--- a/drivers/gpu/drm/meson/meson_drv.c	2022-12-19 17:13:12.677518989 +0800
2949+++ b/drivers/gpu/drm/meson/meson_drv.c	2023-02-23 17:02:04.955751014 +0800
2950@@ -15,6 +15,7 @@
2951 #include <linux/platform_device.h>
2952 #include <linux/soc/amlogic/meson-canvas.h>
2953
2954+#include <drm/drm_aperture.h>
2955 #include <drm/drm_atomic_helper.h>
2956 #include <drm/drm_drv.h>
2957 #include <drm/drm_fb_helper.h>
2958@@ -29,9 +30,12 @@
2959 #include "meson_drv.h"
2960 #include "meson_overlay.h"
2961 #include "meson_plane.h"
2962+#include "meson_cursor.h"
2963 #include "meson_osd_afbcd.h"
2964 #include "meson_registers.h"
2965-#include "meson_venc_cvbs.h"
2966+#include "meson_encoder_cvbs.h"
2967+#include "meson_encoder_hdmi.h"
2968+#include "meson_encoder_dsi.h"
2969 #include "meson_viu.h"
2970 #include "meson_vpp.h"
2971 #include "meson_rdma.h"
2972@@ -93,9 +97,6 @@
2973 static struct drm_driver meson_driver = {
2974 	.driver_features	= DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
2975
2976-	/* IRQ */
2977-	.irq_handler		= meson_irq,
2978-
2979 	/* CMA Ops */
2980 	DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(meson_dumb_create),
2981
2982@@ -159,23 +160,6 @@
2983 	writel_relaxed(value, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
2984 }
2985
2986-static void meson_remove_framebuffers(void)
2987-{
2988-	struct apertures_struct *ap;
2989-
2990-	ap = alloc_apertures(1);
2991-	if (!ap)
2992-		return;
2993-
2994-	/* The framebuffer can be located anywhere in RAM */
2995-	ap->ranges[0].base = 0;
2996-	ap->ranges[0].size = ~0;
2997-
2998-	drm_fb_helper_remove_conflicting_framebuffers(ap, "meson-drm-fb",
2999-						      false);
3000-	kfree(ap);
3001-}
3002-
3003 struct meson_drm_soc_attr {
3004 	struct meson_drm_soc_limits limits;
3005 	const struct soc_device_attribute *attrs;
3006@@ -229,8 +213,7 @@
3007 	priv->compat = match->compat;
3008 	priv->afbcd.ops = match->afbcd_ops;
3009
3010-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu");
3011-	regs = devm_ioremap_resource(dev, res);
3012+	regs = devm_platform_ioremap_resource_byname(pdev, "vpu");
3013 	if (IS_ERR(regs)) {
3014 		ret = PTR_ERR(regs);
3015 		goto free_drm;
3016@@ -267,6 +250,9 @@
3017 	ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd1);
3018 	if (ret)
3019 		goto free_drm;
3020+	ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_osd2);
3021+	if (ret)
3022+		goto free_drm;
3023 	ret = meson_canvas_alloc(priv->canvas, &priv->canvas_id_vd1_0);
3024 	if (ret) {
3025 		meson_canvas_free(priv->canvas, priv->canvas_id_osd1);
3026@@ -300,8 +286,13 @@
3027 		}
3028 	}
3029
3030-	/* Remove early framebuffers (ie. simplefb) */
3031-	meson_remove_framebuffers();
3032+	/*
3033+	 * Remove early framebuffers (ie. simplefb). The framebuffer can be
3034+	 * located anywhere in RAM
3035+	 */
3036+	ret = drm_aperture_remove_framebuffers(false, &meson_driver);
3037+	if (ret)
3038+		goto free_drm;
3039
3040 	ret = drmm_mode_config_init(drm);
3041 	if (ret)
3042@@ -325,33 +316,47 @@
3043
3044 	/* Encoder Initialization */
3045
3046-	ret = meson_venc_cvbs_create(priv);
3047+	ret = meson_encoder_cvbs_init(priv);
3048 	if (ret)
3049-		goto free_drm;
3050+		goto exit_afbcd;
3051
3052 	if (has_components) {
3053 		ret = component_bind_all(drm->dev, drm);
3054 		if (ret) {
3055 			dev_err(drm->dev, "Couldn't bind all components\n");
3056-			goto free_drm;
3057+			goto exit_afbcd;
3058 		}
3059 	}
3060
3061+	ret = meson_encoder_hdmi_init(priv);
3062+	if (ret)
3063+		goto exit_afbcd;
3064+
3065+	ret = meson_cursor_create(priv);
3066+	if (ret)
3067+		goto exit_afbcd;
3068+
3069+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
3070+		ret = meson_encoder_dsi_init(priv);
3071+		if (ret)
3072+			goto free_drm;
3073+	}
3074+
3075 	ret = meson_plane_create(priv);
3076 	if (ret)
3077-		goto free_drm;
3078+		goto exit_afbcd;
3079
3080 	ret = meson_overlay_create(priv);
3081 	if (ret)
3082-		goto free_drm;
3083+		goto exit_afbcd;
3084
3085 	ret = meson_crtc_create(priv);
3086 	if (ret)
3087-		goto free_drm;
3088+		goto exit_afbcd;
3089
3090-	ret = drm_irq_install(drm, priv->vsync_irq);
3091+	ret = request_irq(priv->vsync_irq, meson_irq, IRQF_SHARED, drm->driver->name, drm);
3092 	if (ret)
3093-		goto free_drm;
3094+		goto exit_afbcd;
3095
3096 	drm_mode_config_reset(drm);
3097
3098@@ -368,7 +373,10 @@
3099 	return 0;
3100
3101 uninstall_irq:
3102-	drm_irq_uninstall(drm);
3103+	free_irq(priv->vsync_irq, drm);
3104+exit_afbcd:
3105+	if (priv->afbcd.ops)
3106+		priv->afbcd.ops->exit(priv);
3107 free_drm:
3108 	drm_dev_put(drm);
3109
3110@@ -396,7 +404,7 @@
3111 	drm_kms_helper_poll_fini(drm);
3112 	drm_atomic_helper_shutdown(drm);
3113 	component_unbind_all(dev, drm);
3114-	drm_irq_uninstall(drm);
3115+	free_irq(priv->vsync_irq, drm);
3116 	drm_dev_put(drm);
3117
3118 	if (priv->afbcd.ops)
3119@@ -443,46 +451,6 @@
3120 	return dev->of_node == data;
3121 }
3122
3123-/* Possible connectors nodes to ignore */
3124-static const struct of_device_id connectors_match[] = {
3125-	{ .compatible = "composite-video-connector" },
3126-	{ .compatible = "svideo-connector" },
3127-	{ .compatible = "hdmi-connector" },
3128-	{ .compatible = "dvi-connector" },
3129-	{}
3130-};
3131-
3132-static int meson_probe_remote(struct platform_device *pdev,
3133-			      struct component_match **match,
3134-			      struct device_node *parent,
3135-			      struct device_node *remote)
3136-{
3137-	struct device_node *ep, *remote_node;
3138-	int count = 1;
3139-
3140-	/* If node is a connector, return and do not add to match table */
3141-	if (of_match_node(connectors_match, remote))
3142-		return 1;
3143-
3144-	component_match_add(&pdev->dev, match, compare_of, remote);
3145-
3146-	for_each_endpoint_of_node(remote, ep) {
3147-		remote_node = of_graph_get_remote_port_parent(ep);
3148-		if (!remote_node ||
3149-		    remote_node == parent || /* Ignore parent endpoint */
3150-		    !of_device_is_available(remote_node)) {
3151-			of_node_put(remote_node);
3152-			continue;
3153-		}
3154-
3155-		count += meson_probe_remote(pdev, match, remote, remote_node);
3156-
3157-		of_node_put(remote_node);
3158-	}
3159-
3160-	return count;
3161-}
3162-
3163 static void meson_drv_shutdown(struct platform_device *pdev)
3164 {
3165 	struct meson_drm *priv = dev_get_drvdata(&pdev->dev);
3166@@ -494,6 +462,13 @@
3167 	drm_atomic_helper_shutdown(priv->drm);
3168 }
3169
3170+/* Possible connectors nodes to ignore */
3171+static const struct of_device_id connectors_match[] = {
3172+	{ .compatible = "composite-video-connector" },
3173+	{ .compatible = "svideo-connector" },
3174+	{}
3175+};
3176+
3177 static int meson_drv_probe(struct platform_device *pdev)
3178 {
3179 	struct component_match *match = NULL;
3180@@ -508,8 +483,21 @@
3181 			continue;
3182 		}
3183
3184-		count += meson_probe_remote(pdev, &match, np, remote);
3185+		/* If an analog connector is detected, count it as an output */
3186+		if (of_match_node(connectors_match, remote)) {
3187+			++count;
3188+			of_node_put(remote);
3189+			continue;
3190+		}
3191+
3192+		dev_dbg(&pdev->dev, "parent %pOF remote match add %pOF parent %s\n",
3193+			np, remote, dev_name(&pdev->dev));
3194+
3195+		component_match_add(&pdev->dev, &match, compare_of, remote);
3196+
3197 		of_node_put(remote);
3198+
3199+		++count;
3200 	}
3201
3202 	if (count && !match)
3203diff -Naur a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
3204--- a/drivers/gpu/drm/meson/meson_drv.h	2022-12-19 17:13:12.677518989 +0800
3205+++ b/drivers/gpu/drm/meson/meson_drv.h	2023-02-23 17:02:04.955751014 +0800
3206@@ -43,12 +43,14 @@
3207
3208 	struct meson_canvas *canvas;
3209 	u8 canvas_id_osd1;
3210+	u8 canvas_id_osd2;
3211 	u8 canvas_id_vd1_0;
3212 	u8 canvas_id_vd1_1;
3213 	u8 canvas_id_vd1_2;
3214
3215 	struct drm_device *drm;
3216 	struct drm_crtc *crtc;
3217+	struct drm_plane *cursor_plane;
3218 	struct drm_plane *primary_plane;
3219 	struct drm_plane *overlay_plane;
3220
3221@@ -82,6 +84,21 @@
3222 		uint32_t osd_blend_din0_scope_h;
3223 		uint32_t osd_blend_din0_scope_v;
3224 		uint32_t osb_blend0_size;
3225+
3226+		bool osd2_enabled;
3227+		bool osd2_interlace;
3228+		bool osd2_commit;
3229+		uint32_t osd2_ctrl_stat;
3230+		uint32_t osd2_ctrl_stat2;
3231+		uint32_t osd2_blk0_cfg[5];
3232+		uint32_t osd2_blk1_cfg4;
3233+		uint32_t osd2_blk2_cfg4;
3234+		uint32_t osd2_addr;
3235+		uint32_t osd2_stride;
3236+		uint32_t osd2_height;
3237+		uint32_t osd2_width;
3238+		uint32_t osd_blend_din3_scope_h;
3239+		uint32_t osd_blend_din3_scope_v;
3240 		uint32_t osb_blend1_size;
3241
3242 		bool vd1_enabled;
3243diff -Naur a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
3244--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c	2022-12-19 17:13:12.677518989 +0800
3245+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c	2023-02-23 17:02:04.955751014 +0800
3246@@ -22,14 +22,11 @@
3247 #include <drm/drm_probe_helper.h>
3248 #include <drm/drm_print.h>
3249
3250-#include <linux/media-bus-format.h>
3251 #include <linux/videodev2.h>
3252
3253 #include "meson_drv.h"
3254 #include "meson_dw_hdmi.h"
3255 #include "meson_registers.h"
3256-#include "meson_vclk.h"
3257-#include "meson_venc.h"
3258
3259 #define DRIVER_NAME "meson-dw-hdmi"
3260 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
3261@@ -135,8 +132,6 @@
3262 };
3263
3264 struct meson_dw_hdmi {
3265-	struct drm_encoder encoder;
3266-	struct drm_bridge bridge;
3267 	struct dw_hdmi_plat_data dw_plat_data;
3268 	struct meson_drm *priv;
3269 	struct device *dev;
3270@@ -148,12 +143,8 @@
3271 	struct regulator *hdmi_supply;
3272 	u32 irq_stat;
3273 	struct dw_hdmi *hdmi;
3274-	unsigned long output_bus_fmt;
3275+	struct drm_bridge *bridge;
3276 };
3277-#define encoder_to_meson_dw_hdmi(x) \
3278-	container_of(x, struct meson_dw_hdmi, encoder)
3279-#define bridge_to_meson_dw_hdmi(x) \
3280-	container_of(x, struct meson_dw_hdmi, bridge)
3281
3282 static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
3283 					const char *compat)
3284@@ -295,14 +286,14 @@
3285
3286 /* Setup PHY bandwidth modes */
3287 static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
3288-				      const struct drm_display_mode *mode)
3289+				      const struct drm_display_mode *mode,
3290+				      bool mode_is_420)
3291 {
3292 	struct meson_drm *priv = dw_hdmi->priv;
3293 	unsigned int pixel_clock = mode->clock;
3294
3295 	/* For 420, pixel clock is half unlike venc clock */
3296-	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
3297-		pixel_clock /= 2;
3298+	if (mode_is_420) pixel_clock /= 2;
3299
3300 	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
3301 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
3302@@ -374,68 +365,25 @@
3303 	mdelay(2);
3304 }
3305
3306-static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
3307-			     const struct drm_display_mode *mode)
3308-{
3309-	struct meson_drm *priv = dw_hdmi->priv;
3310-	int vic = drm_match_cea_mode(mode);
3311-	unsigned int phy_freq;
3312-	unsigned int vclk_freq;
3313-	unsigned int venc_freq;
3314-	unsigned int hdmi_freq;
3315-
3316-	vclk_freq = mode->clock;
3317-
3318-	/* For 420, pixel clock is half unlike venc clock */
3319-	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
3320-		vclk_freq /= 2;
3321-
3322-	/* TMDS clock is pixel_clock * 10 */
3323-	phy_freq = vclk_freq * 10;
3324-
3325-	if (!vic) {
3326-		meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
3327-				 vclk_freq, vclk_freq, vclk_freq, false);
3328-		return;
3329-	}
3330-
3331-	/* 480i/576i needs global pixel doubling */
3332-	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
3333-		vclk_freq *= 2;
3334-
3335-	venc_freq = vclk_freq;
3336-	hdmi_freq = vclk_freq;
3337-
3338-	/* VENC double pixels for 1080i, 720p and YUV420 modes */
3339-	if (meson_venc_hdmi_venc_repeat(vic) ||
3340-	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
3341-		venc_freq *= 2;
3342-
3343-	vclk_freq = max(venc_freq, hdmi_freq);
3344-
3345-	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
3346-		venc_freq /= 2;
3347-
3348-	DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
3349-		phy_freq, vclk_freq, venc_freq, hdmi_freq,
3350-		priv->venc.hdmi_use_enci);
3351-
3352-	meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
3353-			 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
3354-}
3355-
3356 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
3357 			    const struct drm_display_info *display,
3358 			    const struct drm_display_mode *mode)
3359 {
3360 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
3361+	bool is_hdmi2_sink = display->hdmi.scdc.supported;
3362 	struct meson_drm *priv = dw_hdmi->priv;
3363 	unsigned int wr_clk =
3364 		readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
3365+	bool mode_is_420 = false;
3366
3367 	DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
3368 			 mode->clock > 340000 ? 40 : 10);
3369
3370+	if (drm_mode_is_420_only(display, mode) ||
3371+	    (!is_hdmi2_sink &&
3372+	     drm_mode_is_420_also(display, mode)))
3373+		mode_is_420 = true;
3374+
3375 	/* Enable clocks */
3376 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
3377
3378@@ -457,8 +405,7 @@
3379 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
3380
3381 	/* TMDS pattern setup */
3382-	if (mode->clock > 340000 &&
3383-	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
3384+	if (mode->clock > 340000 && !mode_is_420) {
3385 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
3386 				  0);
3387 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
3388@@ -476,7 +423,7 @@
3389 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
3390
3391 	/* Setup PHY parameters */
3392-	meson_hdmi_phy_setup_mode(dw_hdmi, mode);
3393+	meson_hdmi_phy_setup_mode(dw_hdmi, mode, mode_is_420);
3394
3395 	/* Setup PHY */
3396 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
3397@@ -622,214 +569,15 @@
3398 		dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
3399 				       hpd_connected);
3400
3401-		drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
3402+		drm_helper_hpd_irq_event(dw_hdmi->bridge->dev);
3403+		drm_bridge_hpd_notify(dw_hdmi->bridge,
3404+				      hpd_connected ? connector_status_connected
3405+						    : connector_status_disconnected);
3406 	}
3407
3408 	return IRQ_HANDLED;
3409 }
3410
3411-static enum drm_mode_status
3412-dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
3413-		   const struct drm_display_info *display_info,
3414-		   const struct drm_display_mode *mode)
3415-{
3416-	struct meson_dw_hdmi *dw_hdmi = data;
3417-	struct meson_drm *priv = dw_hdmi->priv;
3418-	bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
3419-	unsigned int phy_freq;
3420-	unsigned int vclk_freq;
3421-	unsigned int venc_freq;
3422-	unsigned int hdmi_freq;
3423-	int vic = drm_match_cea_mode(mode);
3424-	enum drm_mode_status status;
3425-
3426-	DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
3427-
3428-	/* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
3429-	if (display_info->max_tmds_clock &&
3430-	    mode->clock > display_info->max_tmds_clock &&
3431-	    !drm_mode_is_420_only(display_info, mode) &&
3432-	    !drm_mode_is_420_also(display_info, mode))
3433-		return MODE_BAD;
3434-
3435-	/* Check against non-VIC supported modes */
3436-	if (!vic) {
3437-		status = meson_venc_hdmi_supported_mode(mode);
3438-		if (status != MODE_OK)
3439-			return status;
3440-
3441-		return meson_vclk_dmt_supported_freq(priv, mode->clock);
3442-	/* Check against supported VIC modes */
3443-	} else if (!meson_venc_hdmi_supported_vic(vic))
3444-		return MODE_BAD;
3445-
3446-	vclk_freq = mode->clock;
3447-
3448-	/* For 420, pixel clock is half unlike venc clock */
3449-	if (drm_mode_is_420_only(display_info, mode) ||
3450-	    (!is_hdmi2_sink &&
3451-	     drm_mode_is_420_also(display_info, mode)))
3452-		vclk_freq /= 2;
3453-
3454-	/* TMDS clock is pixel_clock * 10 */
3455-	phy_freq = vclk_freq * 10;
3456-
3457-	/* 480i/576i needs global pixel doubling */
3458-	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
3459-		vclk_freq *= 2;
3460-
3461-	venc_freq = vclk_freq;
3462-	hdmi_freq = vclk_freq;
3463-
3464-	/* VENC double pixels for 1080i, 720p and YUV420 modes */
3465-	if (meson_venc_hdmi_venc_repeat(vic) ||
3466-	    drm_mode_is_420_only(display_info, mode) ||
3467-	    (!is_hdmi2_sink &&
3468-	     drm_mode_is_420_also(display_info, mode)))
3469-		venc_freq *= 2;
3470-
3471-	vclk_freq = max(venc_freq, hdmi_freq);
3472-
3473-	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
3474-		venc_freq /= 2;
3475-
3476-	dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
3477-		__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
3478-
3479-	return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
3480-}
3481-
3482-/* Encoder */
3483-
3484-static const u32 meson_dw_hdmi_out_bus_fmts[] = {
3485-	MEDIA_BUS_FMT_YUV8_1X24,
3486-	MEDIA_BUS_FMT_UYYVYY8_0_5X24,
3487-};
3488-
3489-static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
3490-{
3491-	drm_encoder_cleanup(encoder);
3492-}
3493-
3494-static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
3495-	.destroy        = meson_venc_hdmi_encoder_destroy,
3496-};
3497-
3498-static u32 *
3499-meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
3500-					struct drm_bridge_state *bridge_state,
3501-					struct drm_crtc_state *crtc_state,
3502-					struct drm_connector_state *conn_state,
3503-					u32 output_fmt,
3504-					unsigned int *num_input_fmts)
3505-{
3506-	u32 *input_fmts = NULL;
3507-	int i;
3508-
3509-	*num_input_fmts = 0;
3510-
3511-	for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
3512-		if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
3513-			*num_input_fmts = 1;
3514-			input_fmts = kcalloc(*num_input_fmts,
3515-					     sizeof(*input_fmts),
3516-					     GFP_KERNEL);
3517-			if (!input_fmts)
3518-				return NULL;
3519-
3520-			input_fmts[0] = output_fmt;
3521-
3522-			break;
3523-		}
3524-	}
3525-
3526-	return input_fmts;
3527-}
3528-
3529-static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
3530-					struct drm_bridge_state *bridge_state,
3531-					struct drm_crtc_state *crtc_state,
3532-					struct drm_connector_state *conn_state)
3533-{
3534-	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
3535-
3536-	dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
3537-
3538-	DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
3539-
3540-	return 0;
3541-}
3542-
3543-static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
3544-{
3545-	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
3546-	struct meson_drm *priv = dw_hdmi->priv;
3547-
3548-	DRM_DEBUG_DRIVER("\n");
3549-
3550-	writel_bits_relaxed(0x3, 0,
3551-			    priv->io_base + _REG(VPU_HDMI_SETTING));
3552-
3553-	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
3554-	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
3555-}
3556-
3557-static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
3558-{
3559-	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
3560-	struct meson_drm *priv = dw_hdmi->priv;
3561-
3562-	DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
3563-
3564-	if (priv->venc.hdmi_use_enci)
3565-		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
3566-	else
3567-		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
3568-}
3569-
3570-static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
3571-				   const struct drm_display_mode *mode,
3572-				   const struct drm_display_mode *adjusted_mode)
3573-{
3574-	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
3575-	struct meson_drm *priv = dw_hdmi->priv;
3576-	int vic = drm_match_cea_mode(mode);
3577-	unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
3578-	bool yuv420_mode = false;
3579-
3580-	DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
3581-
3582-	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
3583-		ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
3584-		yuv420_mode = true;
3585-	}
3586-
3587-	/* VENC + VENC-DVI Mode setup */
3588-	meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
3589-
3590-	/* VCLK Set clock */
3591-	dw_hdmi_set_vclk(dw_hdmi, mode);
3592-
3593-	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
3594-		/* Setup YUV420 to HDMI-TX, no 10bit diphering */
3595-		writel_relaxed(2 | (2 << 2),
3596-			       priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
3597-	else
3598-		/* Setup YUV444 to HDMI-TX, no 10bit diphering */
3599-		writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
3600-}
3601-
3602-static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
3603-	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
3604-	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
3605-	.atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
3606-	.atomic_reset = drm_atomic_helper_bridge_reset,
3607-	.atomic_check = meson_venc_hdmi_encoder_atomic_check,
3608-	.enable	= meson_venc_hdmi_encoder_enable,
3609-	.disable = meson_venc_hdmi_encoder_disable,
3610-	.mode_set = meson_venc_hdmi_encoder_mode_set,
3611-};
3612-
3613 /* DW HDMI Regmap */
3614
3615 static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
3616@@ -876,28 +624,6 @@
3617 	.dwc_write = dw_hdmi_g12a_dwc_write,
3618 };
3619
3620-static bool meson_hdmi_connector_is_available(struct device *dev)
3621-{
3622-	struct device_node *ep, *remote;
3623-
3624-	/* HDMI Connector is on the second port, first endpoint */
3625-	ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
3626-	if (!ep)
3627-		return false;
3628-
3629-	/* If the endpoint node exists, consider it enabled */
3630-	remote = of_graph_get_remote_port(ep);
3631-	if (remote) {
3632-		of_node_put(ep);
3633-		return true;
3634-	}
3635-
3636-	of_node_put(ep);
3637-	of_node_put(remote);
3638-
3639-	return false;
3640-}
3641-
3642 static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
3643 {
3644 	struct meson_drm *priv = meson_dw_hdmi->priv;
3645@@ -976,19 +702,11 @@
3646 	struct drm_device *drm = data;
3647 	struct meson_drm *priv = drm->dev_private;
3648 	struct dw_hdmi_plat_data *dw_plat_data;
3649-	struct drm_bridge *next_bridge;
3650-	struct drm_encoder *encoder;
3651-	struct resource *res;
3652 	int irq;
3653 	int ret;
3654
3655 	DRM_DEBUG_DRIVER("\n");
3656
3657-	if (!meson_hdmi_connector_is_available(dev)) {
3658-		dev_info(drm->dev, "HDMI Output connector not available\n");
3659-		return -ENODEV;
3660-	}
3661-
3662 	match = of_device_get_match_data(&pdev->dev);
3663 	if (!match) {
3664 		dev_err(&pdev->dev, "failed to get match data\n");
3665@@ -1004,7 +722,6 @@
3666 	meson_dw_hdmi->dev = dev;
3667 	meson_dw_hdmi->data = match;
3668 	dw_plat_data = &meson_dw_hdmi->dw_plat_data;
3669-	encoder = &meson_dw_hdmi->encoder;
3670
3671 	meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
3672 	if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
3673@@ -1042,8 +759,7 @@
3674 		return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
3675 	}
3676
3677-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3678-	meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
3679+	meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0);
3680 	if (IS_ERR(meson_dw_hdmi->hdmitx))
3681 		return PTR_ERR(meson_dw_hdmi->hdmitx);
3682
3683@@ -1076,33 +792,18 @@
3684 		return ret;
3685 	}
3686
3687-	/* Encoder */
3688-
3689-	ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
3690-			       DRM_MODE_ENCODER_TMDS, "meson_hdmi");
3691-	if (ret) {
3692-		dev_err(priv->dev, "Failed to init HDMI encoder\n");
3693-		return ret;
3694-	}
3695-
3696-	meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
3697-	drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
3698-
3699-	encoder->possible_crtcs = BIT(0);
3700-
3701 	meson_dw_hdmi_init(meson_dw_hdmi);
3702
3703-	DRM_DEBUG_DRIVER("encoder initialized\n");
3704-
3705 	/* Bridge / Connector */
3706
3707 	dw_plat_data->priv_data = meson_dw_hdmi;
3708-	dw_plat_data->mode_valid = dw_hdmi_mode_valid;
3709 	dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
3710 	dw_plat_data->phy_name = "meson_dw_hdmi_phy";
3711 	dw_plat_data->phy_data = meson_dw_hdmi;
3712 	dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
3713 	dw_plat_data->ycbcr_420_allowed = true;
3714+	dw_plat_data->disable_cec = true;
3715+	dw_plat_data->output_port = 1;
3716
3717 	if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
3718 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
3719@@ -1111,15 +812,15 @@
3720
3721 	platform_set_drvdata(pdev, meson_dw_hdmi);
3722
3723-	meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
3724-					    &meson_dw_hdmi->dw_plat_data);
3725+	meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev, &meson_dw_hdmi->dw_plat_data);
3726 	if (IS_ERR(meson_dw_hdmi->hdmi))
3727 		return PTR_ERR(meson_dw_hdmi->hdmi);
3728
3729-	next_bridge = of_drm_find_bridge(pdev->dev.of_node);
3730-	if (next_bridge)
3731-		drm_bridge_attach(encoder, next_bridge,
3732-				  &meson_dw_hdmi->bridge, 0);
3733+	meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node);
3734+
3735+#ifdef CONFIG_DRIVERS_HDF_AUDIO
3736+	dw_hdmi_audio_enable(meson_dw_hdmi->hdmi);
3737+#endif
3738
3739 	DRM_DEBUG_DRIVER("HDMI controller initialized\n");
3740
3741diff -Naur a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
3742--- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c	1970-01-01 08:00:00.000000000 +0800
3743+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c	2023-02-23 17:02:04.955751014 +0800
3744@@ -0,0 +1,364 @@
3745+// SPDX-License-Identifier: GPL-2.0-or-later
3746+/*
3747+ * Copyright (C) 2021 BayLibre, SAS
3748+ * Author: Neil Armstrong <narmstrong@baylibre.com>
3749+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
3750+ */
3751+
3752+#include <linux/clk.h>
3753+#include <linux/component.h>
3754+#include <linux/kernel.h>
3755+#include <linux/module.h>
3756+#include <linux/of_device.h>
3757+#include <linux/of_graph.h>
3758+#include <linux/reset.h>
3759+#include <linux/phy/phy.h>
3760+#include <linux/bitfield.h>
3761+
3762+#include <video/mipi_display.h>
3763+
3764+#include <drm/bridge/dw_mipi_dsi.h>
3765+#include <drm/drm_mipi_dsi.h>
3766+
3767+#include <drm/drm_atomic_helper.h>
3768+#include <drm/drm_device.h>
3769+#include <drm/drm_probe_helper.h>
3770+#include <drm/drm_print.h>
3771+
3772+#include "meson_drv.h"
3773+#include "meson_dw_mipi_dsi.h"
3774+#include "meson_registers.h"
3775+#include "meson_venc.h"
3776+
3777+#define DRIVER_NAME "meson-dw-mipi-dsi"
3778+#define DRIVER_DESC "Amlogic Meson MIPI-DSI DRM driver"
3779+
3780+struct meson_dw_mipi_dsi {
3781+	struct meson_drm *priv;
3782+	struct device *dev;
3783+	void __iomem *base;
3784+	struct phy *phy;
3785+	union phy_configure_opts phy_opts;
3786+	struct dw_mipi_dsi *dmd;
3787+	struct dw_mipi_dsi_plat_data pdata;
3788+	struct mipi_dsi_device *dsi_device;
3789+	const struct drm_display_mode *mode;
3790+	struct clk *px_clk;
3791+};
3792+
3793+#define encoder_to_meson_dw_mipi_dsi(x) \
3794+	container_of(x, struct meson_dw_mipi_dsi, encoder)
3795+
3796+static void meson_dw_mipi_dsi_hw_init(struct meson_dw_mipi_dsi *mipi_dsi)
3797+{
3798+	/* Software reset */
3799+	writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
3800+			    MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
3801+			    MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
3802+			    MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
3803+			    mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
3804+	writel_bits_relaxed(MIPI_DSI_TOP_SW_RESET_DWC | MIPI_DSI_TOP_SW_RESET_INTR |
3805+			    MIPI_DSI_TOP_SW_RESET_DPI | MIPI_DSI_TOP_SW_RESET_TIMING,
3806+			    0, mipi_dsi->base + MIPI_DSI_TOP_SW_RESET);
3807+
3808+	/* Enable clocks */
3809+	writel_bits_relaxed(MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
3810+			    MIPI_DSI_TOP_CLK_SYSCLK_EN | MIPI_DSI_TOP_CLK_PIXCLK_EN,
3811+			    mipi_dsi->base + MIPI_DSI_TOP_CLK_CNTL);
3812+
3813+	/* Take memory out of power down */
3814+	writel_relaxed(0, mipi_dsi->base + MIPI_DSI_TOP_MEM_PD);
3815+}
3816+
3817+static int dw_mipi_dsi_phy_init(void *priv_data)
3818+{
3819+	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
3820+	unsigned int dpi_data_format, venc_data_width;
3821+	int ret;
3822+
3823+	ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
3824+	if (ret) {
3825+		pr_err("Failed to set DSI PLL rate %lu\n",
3826+		       mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
3827+
3828+		return ret;
3829+	}
3830+
3831+	switch (mipi_dsi->dsi_device->format) {
3832+	case MIPI_DSI_FMT_RGB888:
3833+		dpi_data_format = DPI_COLOR_24BIT;
3834+		venc_data_width = VENC_IN_COLOR_24B;
3835+		break;
3836+	case MIPI_DSI_FMT_RGB666:
3837+		dpi_data_format = DPI_COLOR_18BIT_CFG_2;
3838+		venc_data_width = VENC_IN_COLOR_18B;
3839+		break;
3840+	case MIPI_DSI_FMT_RGB666_PACKED:
3841+	case MIPI_DSI_FMT_RGB565:
3842+		return -EINVAL;
3843+	};
3844+
3845+	/* Configure color format for DPI register */
3846+	writel_relaxed(FIELD_PREP(MIPI_DSI_TOP_DPI_COLOR_MODE, dpi_data_format) |
3847+		       FIELD_PREP(MIPI_DSI_TOP_IN_COLOR_MODE, venc_data_width) |
3848+		       FIELD_PREP(MIPI_DSI_TOP_COMP2_SEL, 2) |
3849+		       FIELD_PREP(MIPI_DSI_TOP_COMP1_SEL, 1) |
3850+		       FIELD_PREP(MIPI_DSI_TOP_COMP0_SEL, 0) |
3851+		       (mipi_dsi->mode->flags & DRM_MODE_FLAG_NHSYNC ?
3852+				0 : MIPI_DSI_TOP_HSYNC_INVERT) |
3853+		       (mipi_dsi->mode->flags & DRM_MODE_FLAG_NVSYNC ?
3854+				0 : MIPI_DSI_TOP_VSYNC_INVERT),
3855+			mipi_dsi->base + MIPI_DSI_TOP_CNTL);
3856+
3857+	return phy_configure(mipi_dsi->phy, &mipi_dsi->phy_opts);
3858+}
3859+
3860+static void dw_mipi_dsi_phy_power_on(void *priv_data)
3861+{
3862+	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
3863+
3864+	if (phy_power_on(mipi_dsi->phy))
3865+		dev_warn(mipi_dsi->dev, "Failed to power on PHY\n");
3866+}
3867+
3868+static void dw_mipi_dsi_phy_power_off(void *priv_data)
3869+{
3870+	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
3871+
3872+	if (phy_power_off(mipi_dsi->phy))
3873+		dev_warn(mipi_dsi->dev, "Failed to power off PHY\n");
3874+}
3875+
3876+static int
3877+dw_mipi_dsi_get_lane_mbps(void *priv_data, const struct drm_display_mode *mode,
3878+			  unsigned long mode_flags, u32 lanes, u32 format,
3879+			  unsigned int *lane_mbps)
3880+{
3881+	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
3882+	int bpp;
3883+
3884+	mipi_dsi->mode = mode;
3885+
3886+	bpp = mipi_dsi_pixel_format_to_bpp(mipi_dsi->dsi_device->format);
3887+
3888+	phy_mipi_dphy_get_default_config(mode->clock * 1000,
3889+					 bpp, mipi_dsi->dsi_device->lanes,
3890+					 &mipi_dsi->phy_opts.mipi_dphy);
3891+
3892+	// UNIONMAN add: Round to 800MHz(needed by waveshare panel) (FIXME)
3893+	if (mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate > 600*1000000) {
3894+		mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate = max(800 * 1000000,
3895+				mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate);
3896+	}
3897+
3898+	*lane_mbps = mipi_dsi->phy_opts.mipi_dphy.hs_clk_rate / 1000000;
3899+
3900+	return 0;
3901+}
3902+
3903+static int
3904+dw_mipi_dsi_phy_get_timing(void *priv_data, unsigned int lane_mbps,
3905+			   struct dw_mipi_dsi_dphy_timing *timing)
3906+{
3907+	/* TOFIX handle other cases */
3908+
3909+	timing->clk_lp2hs = 37;
3910+	timing->clk_hs2lp = 135;
3911+	timing->data_lp2hs = 50;
3912+	timing->data_hs2lp = 3;
3913+
3914+	return 0;
3915+}
3916+
3917+static int
3918+dw_mipi_dsi_get_esc_clk_rate(void *priv_data, unsigned int *esc_clk_rate)
3919+{
3920+	*esc_clk_rate = 4; /* Mhz */
3921+
3922+	return 0;
3923+}
3924+
3925+static const struct dw_mipi_dsi_phy_ops meson_dw_mipi_dsi_phy_ops = {
3926+	.init = dw_mipi_dsi_phy_init,
3927+	.power_on = dw_mipi_dsi_phy_power_on,
3928+	.power_off = dw_mipi_dsi_phy_power_off,
3929+	.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
3930+	.get_timing = dw_mipi_dsi_phy_get_timing,
3931+	.get_esc_clk_rate = dw_mipi_dsi_get_esc_clk_rate,
3932+};
3933+
3934+static int meson_dw_mipi_dsi_bind(struct device *dev, struct device *master, void *data)
3935+{
3936+	struct meson_dw_mipi_dsi *mipi_dsi = dev_get_drvdata(dev);
3937+	struct drm_device *drm = data;
3938+	struct meson_drm *priv = drm->dev_private;
3939+
3940+	/* Check before if we are supposed to have a sub-device... */
3941+	if (!mipi_dsi->dsi_device) {
3942+		dw_mipi_dsi_remove(mipi_dsi->dmd);
3943+		return -EPROBE_DEFER;
3944+	}
3945+
3946+	mipi_dsi->priv = priv;
3947+
3948+	meson_dw_mipi_dsi_hw_init(mipi_dsi);
3949+
3950+	return 0;
3951+}
3952+
3953+static const struct component_ops meson_dw_mipi_dsi_ops = {
3954+	.bind	= meson_dw_mipi_dsi_bind,
3955+};
3956+
3957+static int meson_dw_mipi_dsi_host_attach(void *priv_data,
3958+					 struct mipi_dsi_device *device)
3959+{
3960+	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
3961+
3962+	mipi_dsi->dsi_device = device;
3963+
3964+	switch (device->format) {
3965+	case MIPI_DSI_FMT_RGB888:
3966+		break;
3967+	case MIPI_DSI_FMT_RGB666:
3968+		break;
3969+	case MIPI_DSI_FMT_RGB666_PACKED:
3970+	case MIPI_DSI_FMT_RGB565:
3971+		dev_err(mipi_dsi->dev, "invalid pixel format %d\n", device->format);
3972+		return -EINVAL;
3973+	};
3974+
3975+	return phy_init(mipi_dsi->phy);
3976+}
3977+
3978+static int meson_dw_mipi_dsi_host_detach(void *priv_data,
3979+					 struct mipi_dsi_device *device)
3980+{
3981+	struct meson_dw_mipi_dsi *mipi_dsi = priv_data;
3982+
3983+	if (device == mipi_dsi->dsi_device)
3984+		mipi_dsi->dsi_device = NULL;
3985+	else
3986+		return -EINVAL;
3987+
3988+	return phy_exit(mipi_dsi->phy);
3989+}
3990+
3991+static const struct dw_mipi_dsi_host_ops meson_dw_mipi_dsi_host_ops = {
3992+	.attach = meson_dw_mipi_dsi_host_attach,
3993+	.detach = meson_dw_mipi_dsi_host_detach,
3994+};
3995+
3996+static int meson_dw_mipi_dsi_probe(struct platform_device *pdev)
3997+{
3998+	struct meson_dw_mipi_dsi *mipi_dsi;
3999+	struct reset_control *top_rst;
4000+	struct resource *res;
4001+	int ret;
4002+
4003+	mipi_dsi = devm_kzalloc(&pdev->dev, sizeof(*mipi_dsi), GFP_KERNEL);
4004+	if (!mipi_dsi)
4005+		return -ENOMEM;
4006+
4007+	mipi_dsi->dev = &pdev->dev;
4008+
4009+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
4010+	mipi_dsi->base = devm_ioremap_resource(&pdev->dev, res);
4011+	if (IS_ERR(mipi_dsi->base))
4012+		return PTR_ERR(mipi_dsi->base);
4013+
4014+	mipi_dsi->phy = devm_phy_get(&pdev->dev, "dphy");
4015+	if (IS_ERR(mipi_dsi->phy)) {
4016+		ret = PTR_ERR(mipi_dsi->phy);
4017+		dev_err(&pdev->dev, "failed to get mipi dphy: %d\n", ret);
4018+		return ret;
4019+	}
4020+
4021+	mipi_dsi->px_clk = devm_clk_get(&pdev->dev, "px_clk");
4022+	if (IS_ERR(mipi_dsi->px_clk)) {
4023+		dev_err(&pdev->dev, "Unable to get PLL clk\n");
4024+		return PTR_ERR(mipi_dsi->px_clk);
4025+	}
4026+
4027+	/*
4028+	 * We use a TOP reset signal because the APB reset signal
4029+	 * is handled by the TOP control registers.
4030+	 */
4031+	top_rst = devm_reset_control_get_exclusive(&pdev->dev, "top");
4032+	if (IS_ERR(top_rst)) {
4033+		ret = PTR_ERR(top_rst);
4034+
4035+		if (ret != -EPROBE_DEFER)
4036+			dev_err(&pdev->dev, "Unable to get reset control: %d\n", ret);
4037+
4038+		return ret;
4039+	}
4040+
4041+	ret = clk_prepare_enable(mipi_dsi->px_clk);
4042+	if (ret) {
4043+		dev_err(&pdev->dev, "Unable to prepare/enable PX clock\n");
4044+		return ret;
4045+	}
4046+
4047+	reset_control_assert(top_rst);
4048+	usleep_range(10, 20);
4049+	reset_control_deassert(top_rst);
4050+
4051+	/* MIPI DSI Controller */
4052+
4053+	mipi_dsi->pdata.base = mipi_dsi->base;
4054+	mipi_dsi->pdata.max_data_lanes = 4;
4055+	mipi_dsi->pdata.phy_ops = &meson_dw_mipi_dsi_phy_ops;
4056+	mipi_dsi->pdata.host_ops = &meson_dw_mipi_dsi_host_ops;
4057+	mipi_dsi->pdata.priv_data = mipi_dsi;
4058+	platform_set_drvdata(pdev, mipi_dsi);
4059+
4060+	mipi_dsi->dmd = dw_mipi_dsi_probe(pdev, &mipi_dsi->pdata);
4061+	if (IS_ERR(mipi_dsi->dmd)) {
4062+		ret = PTR_ERR(mipi_dsi->dmd);
4063+		if (ret != -EPROBE_DEFER)
4064+			dev_err(&pdev->dev,
4065+				"Failed to probe dw_mipi_dsi: %d\n", ret);
4066+		goto err_clkdisable;
4067+	}
4068+
4069+	return component_add(mipi_dsi->dev, &meson_dw_mipi_dsi_ops);
4070+
4071+err_clkdisable:
4072+	clk_disable_unprepare(mipi_dsi->px_clk);
4073+
4074+	return ret;
4075+}
4076+
4077+static int meson_dw_mipi_dsi_remove(struct platform_device *pdev)
4078+{
4079+	struct meson_dw_mipi_dsi *mipi_dsi = dev_get_drvdata(&pdev->dev);
4080+
4081+	dw_mipi_dsi_remove(mipi_dsi->dmd);
4082+
4083+	component_del(mipi_dsi->dev, &meson_dw_mipi_dsi_ops);
4084+
4085+	clk_disable_unprepare(mipi_dsi->px_clk);
4086+
4087+	return 0;
4088+}
4089+
4090+static const struct of_device_id meson_dw_mipi_dsi_of_table[] = {
4091+	{ .compatible = "amlogic,meson-g12a-dw-mipi-dsi", },
4092+	{ }
4093+};
4094+MODULE_DEVICE_TABLE(of, meson_dw_mipi_dsi_of_table);
4095+
4096+static struct platform_driver meson_dw_mipi_dsi_platform_driver = {
4097+	.probe		= meson_dw_mipi_dsi_probe,
4098+	.remove		= meson_dw_mipi_dsi_remove,
4099+	.driver		= {
4100+		.name		= DRIVER_NAME,
4101+		.of_match_table	= meson_dw_mipi_dsi_of_table,
4102+	},
4103+};
4104+module_platform_driver(meson_dw_mipi_dsi_platform_driver);
4105+
4106+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
4107+MODULE_DESCRIPTION(DRIVER_DESC);
4108+MODULE_LICENSE("GPL");
4109diff -Naur a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h
4110--- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h	1970-01-01 08:00:00.000000000 +0800
4111+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.h	2023-02-23 17:02:04.955751014 +0800
4112@@ -0,0 +1,160 @@
4113+/* SPDX-License-Identifier: GPL-2.0-or-later */
4114+/*
4115+ * Copyright (C) 2020 BayLibre, SAS
4116+ * Author: Neil Armstrong <narmstrong@baylibre.com>
4117+ * Copyright (C) 2018 Amlogic, Inc. All rights reserved.
4118+ */
4119+
4120+#ifndef __MESON_DW_MIPI_DSI_H
4121+#define __MESON_DW_MIPI_DSI_H
4122+
4123+/* Top-level registers */
4124+/* [31: 4]    Reserved.     Default 0.
4125+ *     [3] RW timing_rst_n: Default 1.
4126+ *		1=Assert SW reset of timing feature.   0=Release reset.
4127+ *     [2] RW dpi_rst_n: Default 1.
4128+ *		1=Assert SW reset on mipi_dsi_host_dpi block.   0=Release reset.
4129+ *     [1] RW intr_rst_n: Default 1.
4130+ *		1=Assert SW reset on mipi_dsi_host_intr block.  0=Release reset.
4131+ *     [0] RW dwc_rst_n:  Default 1.
4132+ *		1=Assert SW reset on IP core.   0=Release reset.
4133+ */
4134+#define MIPI_DSI_TOP_SW_RESET                      0x3c0
4135+
4136+#define MIPI_DSI_TOP_SW_RESET_DWC	BIT(0)
4137+#define MIPI_DSI_TOP_SW_RESET_INTR	BIT(1)
4138+#define MIPI_DSI_TOP_SW_RESET_DPI	BIT(2)
4139+#define MIPI_DSI_TOP_SW_RESET_TIMING	BIT(3)
4140+
4141+/* [31: 5] Reserved.   Default 0.
4142+ *     [4] RW manual_edpihalt: Default 0.
4143+ *		1=Manual suspend VencL; 0=do not suspend VencL.
4144+ *     [3] RW auto_edpihalt_en: Default 0.
4145+ *		1=Enable IP's edpihalt signal to suspend VencL;
4146+ *		0=IP's edpihalt signal does not affect VencL.
4147+ *     [2] RW clock_freerun: Apply to auto-clock gate only. Default 0.
4148+ *		0=Default, use auto-clock gating to save power;
4149+ *		1=use free-run clock, disable auto-clock gating, for debug mode.
4150+ *     [1] RW enable_pixclk: A manual clock gate option, due to DWC IP does not
4151+ *		have auto-clock gating. 1=Enable pixclk.      Default 0.
4152+ *     [0] RW enable_sysclk: A manual clock gate option, due to DWC IP does not
4153+ *		have auto-clock gating. 1=Enable sysclk.      Default 0.
4154+ */
4155+#define MIPI_DSI_TOP_CLK_CNTL                      0x3c4
4156+
4157+#define MIPI_DSI_TOP_CLK_SYSCLK_EN	BIT(0)
4158+#define MIPI_DSI_TOP_CLK_PIXCLK_EN	BIT(1)
4159+
4160+/* [31:24]    Reserved. Default 0.
4161+ * [23:20] RW dpi_color_mode: Define DPI pixel format. Default 0.
4162+ *		0=16-bit RGB565 config 1;
4163+ *		1=16-bit RGB565 config 2;
4164+ *		2=16-bit RGB565 config 3;
4165+ *		3=18-bit RGB666 config 1;
4166+ *		4=18-bit RGB666 config 2;
4167+ *		5=24-bit RGB888;
4168+ *		6=20-bit YCbCr 4:2:2;
4169+ *		7=24-bit YCbCr 4:2:2;
4170+ *		8=16-bit YCbCr 4:2:2;
4171+ *		9=30-bit RGB;
4172+ *		10=36-bit RGB;
4173+ *		11=12-bit YCbCr 4:2:0.
4174+ *    [19] Reserved. Default 0.
4175+ * [18:16] RW in_color_mode:  Define VENC data width. Default 0.
4176+ *		0=30-bit pixel;
4177+ *		1=24-bit pixel;
4178+ *		2=18-bit pixel, RGB666;
4179+ *		3=16-bit pixel, RGB565.
4180+ * [15:14] RW chroma_subsample: Define method of chroma subsampling. Default 0.
4181+ *		Applicable to YUV422 or YUV420 only.
4182+ *		0=Use even pixel's chroma;
4183+ *		1=Use odd pixel's chroma;
4184+ *		2=Use averaged value between even and odd pair.
4185+ * [13:12] RW comp2_sel:  Select which component to be Cr or B: Default 2.
4186+ *		0=comp0; 1=comp1; 2=comp2.
4187+ * [11:10] RW comp1_sel:  Select which component to be Cb or G: Default 1.
4188+ *		0=comp0; 1=comp1; 2=comp2.
4189+ *  [9: 8] RW comp0_sel:  Select which component to be Y  or R: Default 0.
4190+ *		0=comp0; 1=comp1; 2=comp2.
4191+ *     [7]    Reserved. Default 0.
4192+ *     [6] RW de_pol:  Default 0.
4193+ *		If DE input is active low, set to 1 to invert to active high.
4194+ *     [5] RW hsync_pol: Default 0.
4195+ *		If HS input is active low, set to 1 to invert to active high.
4196+ *     [4] RW vsync_pol: Default 0.
4197+ *		If VS input is active low, set to 1 to invert to active high.
4198+ *     [3] RW dpicolorm: Signal to IP.   Default 0.
4199+ *     [2] RW dpishutdn: Signal to IP.   Default 0.
4200+ *     [1]    Reserved.  Default 0.
4201+ *     [0]    Reserved.  Default 0.
4202+ */
4203+#define MIPI_DSI_TOP_CNTL                          0x3c8
4204+
4205+/* VENC data width */
4206+#define VENC_IN_COLOR_30B   0x0
4207+#define VENC_IN_COLOR_24B   0x1
4208+#define VENC_IN_COLOR_18B   0x2
4209+#define VENC_IN_COLOR_16B   0x3
4210+
4211+/* DPI pixel format */
4212+#define DPI_COLOR_16BIT_CFG_1		0
4213+#define DPI_COLOR_16BIT_CFG_2		1
4214+#define DPI_COLOR_16BIT_CFG_3		2
4215+#define DPI_COLOR_18BIT_CFG_1		3
4216+#define DPI_COLOR_18BIT_CFG_2		4
4217+#define DPI_COLOR_24BIT			5
4218+#define DPI_COLOR_20BIT_YCBCR_422	6
4219+#define DPI_COLOR_24BIT_YCBCR_422	7
4220+#define DPI_COLOR_16BIT_YCBCR_422	8
4221+#define DPI_COLOR_30BIT			9
4222+#define DPI_COLOR_36BIT			10
4223+#define DPI_COLOR_12BIT_YCBCR_420	11
4224+
4225+#define MIPI_DSI_TOP_DPI_COLOR_MODE	GENMASK(23, 20)
4226+#define MIPI_DSI_TOP_IN_COLOR_MODE	GENMASK(18, 16)
4227+#define MIPI_DSI_TOP_CHROMA_SUBSAMPLE	GENMASK(15, 14)
4228+#define MIPI_DSI_TOP_COMP2_SEL		GENMASK(13, 12)
4229+#define MIPI_DSI_TOP_COMP1_SEL		GENMASK(11, 10)
4230+#define MIPI_DSI_TOP_COMP0_SEL		GENMASK(9, 8)
4231+#define MIPI_DSI_TOP_DE_INVERT		BIT(6)
4232+#define MIPI_DSI_TOP_HSYNC_INVERT	BIT(5)
4233+#define MIPI_DSI_TOP_VSYNC_INVERT	BIT(4)
4234+#define MIPI_DSI_TOP_DPICOLORM		BIT(3)
4235+#define MIPI_DSI_TOP_DPISHUTDN		BIT(2)
4236+
4237+#define MIPI_DSI_TOP_SUSPEND_CNTL                  0x3cc
4238+#define MIPI_DSI_TOP_SUSPEND_LINE                  0x3d0
4239+#define MIPI_DSI_TOP_SUSPEND_PIX                   0x3d4
4240+#define MIPI_DSI_TOP_MEAS_CNTL                     0x3d8
4241+/* [0] R  stat_edpihalt:  edpihalt signal from IP.    Default 0. */
4242+#define MIPI_DSI_TOP_STAT                          0x3dc
4243+#define MIPI_DSI_TOP_MEAS_STAT_TE0                 0x3e0
4244+#define MIPI_DSI_TOP_MEAS_STAT_TE1                 0x3e4
4245+#define MIPI_DSI_TOP_MEAS_STAT_VS0                 0x3e8
4246+#define MIPI_DSI_TOP_MEAS_STAT_VS1                 0x3ec
4247+/* [31:16] RW intr_stat/clr. Default 0.
4248+ *		For each bit, read as this interrupt level status,
4249+ *		write 1 to clear.
4250+ * [31:22] Reserved
4251+ * [   21] stat/clr of eof interrupt
4252+ * [   21] vde_fall interrupt
4253+ * [   19] stat/clr of de_rise interrupt
4254+ * [   18] stat/clr of vs_fall interrupt
4255+ * [   17] stat/clr of vs_rise interrupt
4256+ * [   16] stat/clr of dwc_edpite interrupt
4257+ * [15: 0] RW intr_enable. Default 0.
4258+ *		For each bit, 1=enable this interrupt, 0=disable.
4259+ *	[15: 6] Reserved
4260+ *	[    5] eof interrupt
4261+ *	[    4] de_fall interrupt
4262+ *	[    3] de_rise interrupt
4263+ *	[    2] vs_fall interrupt
4264+ *	[    1] vs_rise interrupt
4265+ *	[    0] dwc_edpite interrupt
4266+ */
4267+#define MIPI_DSI_TOP_INTR_CNTL_STAT                0x3f0
4268+// 31: 2    Reserved.   Default 0.
4269+//  1: 0 RW mem_pd.     Default 3.
4270+#define MIPI_DSI_TOP_MEM_PD                        0x3f4
4271+
4272+#endif /* __MESON_DW_MIPI_DSI_H */
4273diff -Naur a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
4274--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c	1970-01-01 08:00:00.000000000 +0800
4275+++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c	2023-02-23 17:02:04.955751014 +0800
4276@@ -0,0 +1,284 @@
4277+// SPDX-License-Identifier: GPL-2.0-or-later
4278+/*
4279+ * Copyright (C) 2016 BayLibre, SAS
4280+ * Author: Neil Armstrong <narmstrong@baylibre.com>
4281+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
4282+ * Copyright (C) 2014 Endless Mobile
4283+ *
4284+ * Written by:
4285+ *     Jasper St. Pierre <jstpierre@mecheye.net>
4286+ */
4287+
4288+#include <linux/export.h>
4289+#include <linux/of_graph.h>
4290+
4291+#include <drm/drm_atomic_helper.h>
4292+#include <drm/drm_bridge.h>
4293+#include <drm/drm_bridge_connector.h>
4294+#include <drm/drm_device.h>
4295+#include <drm/drm_edid.h>
4296+#include <drm/drm_probe_helper.h>
4297+#include <drm/drm_simple_kms_helper.h>
4298+
4299+#include "meson_registers.h"
4300+#include "meson_vclk.h"
4301+#include "meson_encoder_cvbs.h"
4302+
4303+/* HHI VDAC Registers */
4304+#define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
4305+#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
4306+#define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
4307+#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
4308+
4309+struct meson_encoder_cvbs {
4310+	struct drm_encoder	encoder;
4311+	struct drm_bridge	bridge;
4312+	struct drm_bridge	*next_bridge;
4313+	struct meson_drm	*priv;
4314+};
4315+
4316+#define bridge_to_meson_encoder_cvbs(x) \
4317+	container_of(x, struct meson_encoder_cvbs, bridge)
4318+
4319+/* Supported Modes */
4320+
4321+struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
4322+	{ /* PAL */
4323+		.enci = &meson_cvbs_enci_pal,
4324+		.mode = {
4325+			DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
4326+				 720, 732, 795, 864, 0, 576, 580, 586, 625, 0,
4327+				 DRM_MODE_FLAG_INTERLACE),
4328+			.picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
4329+		},
4330+	},
4331+	{ /* NTSC */
4332+		.enci = &meson_cvbs_enci_ntsc,
4333+		.mode = {
4334+			DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
4335+				720, 739, 801, 858, 0, 480, 488, 494, 525, 0,
4336+				DRM_MODE_FLAG_INTERLACE),
4337+			.picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
4338+		},
4339+	},
4340+};
4341+
4342+static const struct meson_cvbs_mode *
4343+meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
4344+{
4345+	int i;
4346+
4347+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
4348+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
4349+
4350+		if (drm_mode_match(req_mode, &meson_mode->mode,
4351+				   DRM_MODE_MATCH_TIMINGS |
4352+				   DRM_MODE_MATCH_CLOCK |
4353+				   DRM_MODE_MATCH_FLAGS |
4354+				   DRM_MODE_MATCH_3D_FLAGS))
4355+			return meson_mode;
4356+	}
4357+
4358+	return NULL;
4359+}
4360+
4361+static int meson_encoder_cvbs_attach(struct drm_bridge *bridge,
4362+				     enum drm_bridge_attach_flags flags)
4363+{
4364+	struct meson_encoder_cvbs *meson_encoder_cvbs =
4365+					bridge_to_meson_encoder_cvbs(bridge);
4366+
4367+	return drm_bridge_attach(bridge->encoder, meson_encoder_cvbs->next_bridge,
4368+				 &meson_encoder_cvbs->bridge, flags);
4369+}
4370+
4371+static int meson_encoder_cvbs_get_modes(struct drm_bridge *bridge,
4372+					struct drm_connector *connector)
4373+{
4374+	struct meson_encoder_cvbs *meson_encoder_cvbs =
4375+					bridge_to_meson_encoder_cvbs(bridge);
4376+	struct meson_drm *priv = meson_encoder_cvbs->priv;
4377+	struct drm_display_mode *mode;
4378+	int i;
4379+
4380+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
4381+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
4382+
4383+		mode = drm_mode_duplicate(priv->drm, &meson_mode->mode);
4384+		if (!mode) {
4385+			dev_err(priv->dev, "Failed to create a new display mode\n");
4386+			return 0;
4387+		}
4388+
4389+		drm_mode_probed_add(connector, mode);
4390+	}
4391+
4392+	return i;
4393+}
4394+
4395+static int meson_encoder_cvbs_mode_valid(struct drm_bridge *bridge,
4396+					const struct drm_display_info *display_info,
4397+					const struct drm_display_mode *mode)
4398+{
4399+	if (meson_cvbs_get_mode(mode))
4400+		return MODE_OK;
4401+
4402+	return MODE_BAD;
4403+}
4404+
4405+static int meson_encoder_cvbs_atomic_check(struct drm_bridge *bridge,
4406+					struct drm_bridge_state *bridge_state,
4407+					struct drm_crtc_state *crtc_state,
4408+					struct drm_connector_state *conn_state)
4409+{
4410+	if (meson_cvbs_get_mode(&crtc_state->mode))
4411+		return 0;
4412+
4413+	return -EINVAL;
4414+}
4415+
4416+static void meson_encoder_cvbs_atomic_enable(struct drm_bridge *bridge,
4417+					     struct drm_bridge_state *bridge_state)
4418+{
4419+	struct meson_encoder_cvbs *encoder_cvbs = bridge_to_meson_encoder_cvbs(bridge);
4420+	struct drm_atomic_state *state = bridge_state->base.state;
4421+	struct meson_drm *priv = encoder_cvbs->priv;
4422+	const struct meson_cvbs_mode *meson_mode;
4423+	struct drm_connector_state *conn_state;
4424+	struct drm_crtc_state *crtc_state;
4425+	struct drm_connector *connector;
4426+
4427+	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
4428+	if (WARN_ON(!connector))
4429+		return;
4430+
4431+	conn_state = drm_atomic_get_new_connector_state(state, connector);
4432+	if (WARN_ON(!conn_state))
4433+		return;
4434+
4435+	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
4436+	if (WARN_ON(!crtc_state))
4437+		return;
4438+
4439+	meson_mode = meson_cvbs_get_mode(&crtc_state->adjusted_mode);
4440+	if (WARN_ON(!meson_mode))
4441+		return;
4442+
4443+	meson_venci_cvbs_mode_set(priv, meson_mode->enci);
4444+
4445+	/* Setup 27MHz vclk2 for ENCI and VDAC */
4446+	meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
4447+			 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
4448+			 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
4449+			 true);
4450+
4451+	/* VDAC0 source is not from ATV */
4452+	writel_bits_relaxed(VENC_VDAC_SEL_ATV_DMD, 0,
4453+			    priv->io_base + _REG(VENC_VDAC_DACSEL0));
4454+
4455+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
4456+		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
4457+		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
4458+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
4459+		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
4460+		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
4461+		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
4462+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
4463+		regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0x906001);
4464+		regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
4465+	}
4466+}
4467+
4468+static void meson_encoder_cvbs_atomic_disable(struct drm_bridge *bridge,
4469+					      struct drm_bridge_state *bridge_state)
4470+{
4471+	struct meson_encoder_cvbs *meson_encoder_cvbs =
4472+					bridge_to_meson_encoder_cvbs(bridge);
4473+	struct meson_drm *priv = meson_encoder_cvbs->priv;
4474+
4475+	/* Disable CVBS VDAC */
4476+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
4477+		regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
4478+		regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
4479+	} else {
4480+		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
4481+		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
4482+	}
4483+}
4484+
4485+static const struct drm_bridge_funcs meson_encoder_cvbs_bridge_funcs = {
4486+	.attach = meson_encoder_cvbs_attach,
4487+	.mode_valid = meson_encoder_cvbs_mode_valid,
4488+	.get_modes = meson_encoder_cvbs_get_modes,
4489+	.atomic_enable = meson_encoder_cvbs_atomic_enable,
4490+	.atomic_disable = meson_encoder_cvbs_atomic_disable,
4491+	.atomic_check = meson_encoder_cvbs_atomic_check,
4492+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
4493+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
4494+	.atomic_reset = drm_atomic_helper_bridge_reset,
4495+};
4496+
4497+int meson_encoder_cvbs_init(struct meson_drm *priv)
4498+{
4499+	struct drm_device *drm = priv->drm;
4500+	struct meson_encoder_cvbs *meson_encoder_cvbs;
4501+	struct drm_connector *connector;
4502+	struct device_node *remote;
4503+	int ret;
4504+
4505+	meson_encoder_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_encoder_cvbs), GFP_KERNEL);
4506+	if (!meson_encoder_cvbs)
4507+		return -ENOMEM;
4508+
4509+	/* CVBS Connector Bridge */
4510+	remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0);
4511+	if (!remote) {
4512+		dev_info(drm->dev, "CVBS Output connector not available\n");
4513+		return 0;
4514+	}
4515+
4516+	meson_encoder_cvbs->next_bridge = of_drm_find_bridge(remote);
4517+	if (!meson_encoder_cvbs->next_bridge) {
4518+		dev_err(priv->dev, "Failed to find CVBS Connector bridge\n");
4519+		return -EPROBE_DEFER;
4520+	}
4521+
4522+	/* CVBS Encoder Bridge */
4523+	meson_encoder_cvbs->bridge.funcs = &meson_encoder_cvbs_bridge_funcs;
4524+	meson_encoder_cvbs->bridge.of_node = priv->dev->of_node;
4525+	meson_encoder_cvbs->bridge.type = DRM_MODE_CONNECTOR_Composite;
4526+	meson_encoder_cvbs->bridge.ops = DRM_BRIDGE_OP_MODES;
4527+	meson_encoder_cvbs->bridge.interlace_allowed = true;
4528+
4529+	drm_bridge_add(&meson_encoder_cvbs->bridge);
4530+
4531+	meson_encoder_cvbs->priv = priv;
4532+
4533+	/* Encoder */
4534+	ret = drm_simple_encoder_init(priv->drm, &meson_encoder_cvbs->encoder,
4535+				      DRM_MODE_ENCODER_TVDAC);
4536+	if (ret) {
4537+		dev_err(priv->dev, "Failed to init CVBS encoder: %d\n", ret);
4538+		return ret;
4539+	}
4540+
4541+	meson_encoder_cvbs->encoder.possible_crtcs = BIT(0);
4542+
4543+	/* Attach CVBS Encoder Bridge to Encoder */
4544+	ret = drm_bridge_attach(&meson_encoder_cvbs->encoder, &meson_encoder_cvbs->bridge, NULL,
4545+				DRM_BRIDGE_ATTACH_NO_CONNECTOR);
4546+	if (ret) {
4547+		dev_err(priv->dev, "Failed to attach bridge: %d\n", ret);
4548+		return ret;
4549+	}
4550+
4551+	/* Initialize & attach Bridge Connector */
4552+	connector = drm_bridge_connector_init(priv->drm, &meson_encoder_cvbs->encoder);
4553+	if (IS_ERR(connector)) {
4554+		dev_err(priv->dev, "Unable to create CVBS bridge connector\n");
4555+		return PTR_ERR(connector);
4556+	}
4557+	drm_connector_attach_encoder(connector, &meson_encoder_cvbs->encoder);
4558+
4559+	return 0;
4560+}
4561diff -Naur a/drivers/gpu/drm/meson/meson_encoder_cvbs.h b/drivers/gpu/drm/meson/meson_encoder_cvbs.h
4562--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.h	1970-01-01 08:00:00.000000000 +0800
4563+++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.h	2023-02-23 17:02:04.955751014 +0800
4564@@ -0,0 +1,29 @@
4565+/* SPDX-License-Identifier: GPL-2.0-or-later */
4566+/*
4567+ * Copyright (C) 2016 BayLibre, SAS
4568+ * Author: Neil Armstrong <narmstrong@baylibre.com>
4569+ * Copyright (C) 2014 Endless Mobile
4570+ *
4571+ * Written by:
4572+ *     Jasper St. Pierre <jstpierre@mecheye.net>
4573+ */
4574+
4575+#ifndef __MESON_VENC_CVBS_H
4576+#define __MESON_VENC_CVBS_H
4577+
4578+#include "meson_drv.h"
4579+#include "meson_venc.h"
4580+
4581+struct meson_cvbs_mode {
4582+	struct meson_cvbs_enci_mode *enci;
4583+	struct drm_display_mode mode;
4584+};
4585+
4586+#define MESON_CVBS_MODES_COUNT	2
4587+
4588+/* Modes supported by the CVBS output */
4589+extern struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT];
4590+
4591+int meson_encoder_cvbs_init(struct meson_drm *priv);
4592+
4593+#endif /* __MESON_VENC_CVBS_H */
4594diff -Naur a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c
4595--- a/drivers/gpu/drm/meson/meson_encoder_dsi.c	1970-01-01 08:00:00.000000000 +0800
4596+++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c	2023-02-23 17:02:04.959751069 +0800
4597@@ -0,0 +1,168 @@
4598+// SPDX-License-Identifier: GPL-2.0-or-later
4599+/*
4600+ * Copyright (C) 2016 BayLibre, SAS
4601+ * Author: Neil Armstrong <narmstrong@baylibre.com>
4602+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
4603+ */
4604+
4605+#include <linux/kernel.h>
4606+#include <linux/module.h>
4607+#include <linux/of_device.h>
4608+#include <linux/of_graph.h>
4609+
4610+#include <drm/drm_atomic_helper.h>
4611+#include <drm/drm_simple_kms_helper.h>
4612+#include <drm/drm_bridge.h>
4613+#include <drm/drm_bridge_connector.h>
4614+#include <drm/drm_device.h>
4615+#include <drm/drm_probe_helper.h>
4616+
4617+#include "meson_drv.h"
4618+#include "meson_encoder_dsi.h"
4619+#include "meson_registers.h"
4620+#include "meson_venc.h"
4621+#include "meson_vclk.h"
4622+
4623+struct meson_encoder_dsi {
4624+	struct drm_encoder encoder;
4625+	struct drm_bridge bridge;
4626+	struct drm_bridge *next_bridge;
4627+	struct meson_drm *priv;
4628+};
4629+
4630+#define bridge_to_meson_encoder_dsi(x) \
4631+	container_of(x, struct meson_encoder_dsi, bridge)
4632+
4633+static int meson_encoder_dsi_attach(struct drm_bridge *bridge,
4634+				    enum drm_bridge_attach_flags flags)
4635+{
4636+	struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge);
4637+
4638+	return drm_bridge_attach(bridge->encoder, encoder_dsi->next_bridge,
4639+				 &encoder_dsi->bridge, flags);
4640+}
4641+
4642+static void meson_encoder_dsi_mode_set(struct drm_bridge *bridge,
4643+				       const struct drm_display_mode *mode,
4644+				       const struct drm_display_mode *adjusted_mode)
4645+{
4646+	struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge);
4647+	struct meson_drm *priv = encoder_dsi->priv;
4648+
4649+	meson_vclk_setup(priv, MESON_VCLK_TARGET_DSI, mode->clock, 0, 0, 0, false);
4650+
4651+	meson_venc_mipi_dsi_mode_set(priv, mode);
4652+	meson_encl_load_gamma(priv);
4653+
4654+	writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
4655+
4656+	writel_bits_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN, ENCL_VIDEO_MODE_ADV_VFIFO_EN,
4657+			    priv->io_base + _REG(ENCL_VIDEO_MODE_ADV));
4658+	writel_relaxed(0, priv->io_base + _REG(ENCL_TST_EN));
4659+}
4660+
4661+static void meson_encoder_dsi_atomic_enable(struct drm_bridge *bridge,
4662+					    struct drm_bridge_state *bridge_state)
4663+{
4664+	struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge);
4665+	struct meson_drm *priv = encoder_dsi->priv;
4666+
4667+	// UNIONMAN add:  fix green/black color distortion issue with DSI
4668+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
4669+		writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT,
4670+				OSD1_HDR2_CTRL_REG_ONLY_MAT,
4671+				priv->io_base + _REG(OSD1_HDR2_CTRL));
4672+		dev_info(priv->dev, "set OSD1_HDR2_CTRL to fix green/black color distortion.\n");
4673+	}
4674+
4675+	writel_bits_relaxed(BIT(0), 0, priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
4676+
4677+	writel_relaxed(1, priv->io_base + _REG(ENCL_VIDEO_EN));
4678+}
4679+
4680+static void meson_encoder_dsi_atomic_disable(struct drm_bridge *bridge,
4681+					     struct drm_bridge_state *bridge_state)
4682+{
4683+	struct meson_encoder_dsi *meson_encoder_dsi =
4684+					bridge_to_meson_encoder_dsi(bridge);
4685+	struct meson_drm *priv = meson_encoder_dsi->priv;
4686+
4687+	writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
4688+
4689+	writel_bits_relaxed(BIT(0), BIT(0), priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
4690+}
4691+
4692+static const struct drm_bridge_funcs meson_encoder_dsi_bridge_funcs = {
4693+	.attach	= meson_encoder_dsi_attach,
4694+	/*
4695+	 * TOFIX: remove when dw-mipi-dsi moves out of mode_set
4696+	 * We should get rid of mode_set, but until dw-mipi-dsi uses it
4697+	 * we need to setup the pixel clock before the following
4698+	 * bridge tries to setup the HW.
4699+	 */
4700+	.mode_set = meson_encoder_dsi_mode_set,
4701+	.atomic_enable = meson_encoder_dsi_atomic_enable,
4702+	.atomic_disable	= meson_encoder_dsi_atomic_disable,
4703+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
4704+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
4705+	.atomic_reset = drm_atomic_helper_bridge_reset,
4706+};
4707+
4708+int meson_encoder_dsi_init(struct meson_drm *priv)
4709+{
4710+	struct meson_encoder_dsi *meson_encoder_dsi;
4711+	struct device_node *remote;
4712+	int ret;
4713+
4714+	meson_encoder_dsi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_dsi), GFP_KERNEL);
4715+	if (!meson_encoder_dsi)
4716+		return -ENOMEM;
4717+
4718+	/* DSI Transceiver Bridge */
4719+	remote = of_graph_get_remote_node(priv->dev->of_node, 2, 0);
4720+	if (!remote) {
4721+		dev_err(priv->dev, "DSI transceiver device is disabled");
4722+		return 0;
4723+	}
4724+
4725+	meson_encoder_dsi->next_bridge = of_drm_find_bridge(remote);
4726+	if (!meson_encoder_dsi->next_bridge) {
4727+		dev_dbg(priv->dev, "Failed to find DSI transceiver bridge: %d\n", ret);
4728+		return -EPROBE_DEFER;
4729+	}
4730+
4731+	/* DSI Encoder Bridge */
4732+	meson_encoder_dsi->bridge.funcs = &meson_encoder_dsi_bridge_funcs;
4733+	meson_encoder_dsi->bridge.of_node = priv->dev->of_node;
4734+	meson_encoder_dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
4735+
4736+	drm_bridge_add(&meson_encoder_dsi->bridge);
4737+
4738+	meson_encoder_dsi->priv = priv;
4739+
4740+	/* Encoder */
4741+	ret = drm_simple_encoder_init(priv->drm, &meson_encoder_dsi->encoder,
4742+				      DRM_MODE_ENCODER_DSI);
4743+	if (ret) {
4744+		dev_err(priv->dev, "Failed to init DSI encoder: %d\n", ret);
4745+		return ret;
4746+	}
4747+
4748+	meson_encoder_dsi->encoder.possible_crtcs = BIT(0);
4749+
4750+	/* Attach DSI Encoder Bridge to Encoder */
4751+	ret = drm_bridge_attach(&meson_encoder_dsi->encoder, &meson_encoder_dsi->bridge, NULL, 0);
4752+	if (ret) {
4753+		dev_err(priv->dev, "Failed to attach bridge: %d\n", ret);
4754+		return ret;
4755+	}
4756+
4757+	/*
4758+	 * We should have now in place:
4759+	 * encoder->[dsi encoder bridge]->[dw-mipi-dsi bridge]->[panel bridge]->[panel]
4760+	 */
4761+
4762+	dev_dbg(priv->dev, "DSI encoder initialized\n");
4763+
4764+	return 0;
4765+}
4766diff -Naur a/drivers/gpu/drm/meson/meson_encoder_dsi.h b/drivers/gpu/drm/meson/meson_encoder_dsi.h
4767--- a/drivers/gpu/drm/meson/meson_encoder_dsi.h	1970-01-01 08:00:00.000000000 +0800
4768+++ b/drivers/gpu/drm/meson/meson_encoder_dsi.h	2023-02-23 17:02:04.959751069 +0800
4769@@ -0,0 +1,12 @@
4770+/* SPDX-License-Identifier: GPL-2.0-or-later */
4771+/*
4772+ * Copyright (C) 2021 BayLibre, SAS
4773+ * Author: Neil Armstrong <narmstrong@baylibre.com>
4774+ */
4775+
4776+#ifndef __MESON_ENCODER_DSI_H
4777+#define __MESON_ENCODER_DSI_H
4778+
4779+int meson_encoder_dsi_init(struct meson_drm *priv);
4780+
4781+#endif /* __MESON_ENCODER_DSI_H */
4782diff -Naur a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
4783--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c	1970-01-01 08:00:00.000000000 +0800
4784+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c	2023-02-23 17:02:04.959751069 +0800
4785@@ -0,0 +1,455 @@
4786+// SPDX-License-Identifier: GPL-2.0-or-later
4787+/*
4788+ * Copyright (C) 2016 BayLibre, SAS
4789+ * Author: Neil Armstrong <narmstrong@baylibre.com>
4790+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
4791+ */
4792+
4793+#include <linux/clk.h>
4794+#include <linux/component.h>
4795+#include <linux/kernel.h>
4796+#include <linux/module.h>
4797+#include <linux/of_device.h>
4798+#include <linux/of_graph.h>
4799+#include <linux/regulator/consumer.h>
4800+#include <linux/reset.h>
4801+
4802+#include <media/cec-notifier.h>
4803+
4804+#include <drm/drm_atomic_helper.h>
4805+#include <drm/drm_bridge.h>
4806+#include <drm/drm_bridge_connector.h>
4807+#include <drm/drm_device.h>
4808+#include <drm/drm_edid.h>
4809+#include <drm/drm_probe_helper.h>
4810+#include <drm/drm_simple_kms_helper.h>
4811+
4812+#include <linux/media-bus-format.h>
4813+#include <linux/videodev2.h>
4814+
4815+#include "meson_drv.h"
4816+#include "meson_registers.h"
4817+#include "meson_vclk.h"
4818+#include "meson_venc.h"
4819+#include "meson_encoder_hdmi.h"
4820+
4821+struct meson_encoder_hdmi {
4822+	struct drm_encoder encoder;
4823+	struct drm_bridge bridge;
4824+	struct drm_bridge *next_bridge;
4825+	struct drm_connector *connector;
4826+	struct meson_drm *priv;
4827+	unsigned long output_bus_fmt;
4828+	struct cec_notifier *cec_notifier;
4829+};
4830+
4831+#define bridge_to_meson_encoder_hdmi(x) \
4832+	container_of(x, struct meson_encoder_hdmi, bridge)
4833+
4834+static int meson_encoder_hdmi_attach(struct drm_bridge *bridge,
4835+				     enum drm_bridge_attach_flags flags)
4836+{
4837+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
4838+
4839+	return drm_bridge_attach(bridge->encoder, encoder_hdmi->next_bridge,
4840+				 &encoder_hdmi->bridge, flags);
4841+}
4842+
4843+static void meson_encoder_hdmi_detach(struct drm_bridge *bridge)
4844+{
4845+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
4846+
4847+	cec_notifier_conn_unregister(encoder_hdmi->cec_notifier);
4848+	encoder_hdmi->cec_notifier = NULL;
4849+}
4850+
4851+static void meson_encoder_hdmi_set_vclk(struct meson_encoder_hdmi *encoder_hdmi,
4852+					const struct drm_display_mode *mode)
4853+{
4854+	struct meson_drm *priv = encoder_hdmi->priv;
4855+	int vic = drm_match_cea_mode(mode);
4856+	unsigned int phy_freq;
4857+	unsigned int vclk_freq;
4858+	unsigned int venc_freq;
4859+	unsigned int hdmi_freq;
4860+
4861+	vclk_freq = mode->clock;
4862+
4863+	/* For 420, pixel clock is half unlike venc clock */
4864+	if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
4865+		vclk_freq /= 2;
4866+
4867+	/* TMDS clock is pixel_clock * 10 */
4868+	phy_freq = vclk_freq * 10;
4869+
4870+	if (!vic) {
4871+		meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
4872+				 vclk_freq, vclk_freq, vclk_freq, false);
4873+		return;
4874+	}
4875+
4876+	/* 480i/576i needs global pixel doubling */
4877+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
4878+		vclk_freq *= 2;
4879+
4880+	venc_freq = vclk_freq;
4881+	hdmi_freq = vclk_freq;
4882+
4883+	/* VENC double pixels for 1080i, 720p and YUV420 modes */
4884+	if (meson_venc_hdmi_venc_repeat(vic) ||
4885+	    encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
4886+		venc_freq *= 2;
4887+
4888+	vclk_freq = max(venc_freq, hdmi_freq);
4889+
4890+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
4891+		venc_freq /= 2;
4892+
4893+	dev_dbg(priv->dev, "vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
4894+		phy_freq, vclk_freq, venc_freq, hdmi_freq,
4895+		priv->venc.hdmi_use_enci);
4896+
4897+	meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
4898+			 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
4899+}
4900+
4901+static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bridge,
4902+					const struct drm_display_info *display_info,
4903+					const struct drm_display_mode *mode)
4904+{
4905+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
4906+	struct meson_drm *priv = encoder_hdmi->priv;
4907+	bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
4908+	unsigned int phy_freq;
4909+	unsigned int vclk_freq;
4910+	unsigned int venc_freq;
4911+	unsigned int hdmi_freq;
4912+	int vic = drm_match_cea_mode(mode);
4913+	enum drm_mode_status status;
4914+
4915+	dev_dbg(priv->dev, "Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
4916+
4917+	/* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
4918+	if (display_info->max_tmds_clock &&
4919+	    mode->clock > display_info->max_tmds_clock &&
4920+	    !drm_mode_is_420_only(display_info, mode) &&
4921+	    !drm_mode_is_420_also(display_info, mode))
4922+		return MODE_BAD;
4923+
4924+	/* Check against non-VIC supported modes */
4925+	if (!vic) {
4926+		status = meson_venc_hdmi_supported_mode(mode);
4927+		if (status != MODE_OK)
4928+			return status;
4929+
4930+		return meson_vclk_dmt_supported_freq(priv, mode->clock);
4931+	/* Check against supported VIC modes */
4932+	} else if (!meson_venc_hdmi_supported_vic(vic))
4933+		return MODE_BAD;
4934+
4935+	vclk_freq = mode->clock;
4936+
4937+	/* For 420, pixel clock is half unlike venc clock */
4938+	if (drm_mode_is_420_only(display_info, mode) ||
4939+	    (!is_hdmi2_sink &&
4940+	     drm_mode_is_420_also(display_info, mode)))
4941+		vclk_freq /= 2;
4942+
4943+	/* TMDS clock is pixel_clock * 10 */
4944+	phy_freq = vclk_freq * 10;
4945+
4946+	/* 480i/576i needs global pixel doubling */
4947+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
4948+		vclk_freq *= 2;
4949+
4950+	venc_freq = vclk_freq;
4951+	hdmi_freq = vclk_freq;
4952+
4953+	/* VENC double pixels for 1080i, 720p and YUV420 modes */
4954+	if (meson_venc_hdmi_venc_repeat(vic) ||
4955+	    drm_mode_is_420_only(display_info, mode) ||
4956+	    (!is_hdmi2_sink &&
4957+	     drm_mode_is_420_also(display_info, mode)))
4958+		venc_freq *= 2;
4959+
4960+	vclk_freq = max(venc_freq, hdmi_freq);
4961+
4962+	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
4963+		venc_freq /= 2;
4964+
4965+	dev_dbg(priv->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
4966+		__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
4967+
4968+	return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
4969+}
4970+
4971+static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
4972+					     struct drm_bridge_state *bridge_state)
4973+{
4974+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
4975+	struct drm_atomic_state *state = bridge_state->base.state;
4976+	unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
4977+	struct meson_drm *priv = encoder_hdmi->priv;
4978+	struct drm_connector_state *conn_state;
4979+	const struct drm_display_mode *mode;
4980+	struct drm_crtc_state *crtc_state;
4981+	struct drm_connector *connector;
4982+	bool yuv420_mode = false;
4983+	int vic;
4984+
4985+	connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
4986+	if (WARN_ON(!connector))
4987+		return;
4988+
4989+	conn_state = drm_atomic_get_new_connector_state(state, connector);
4990+	if (WARN_ON(!conn_state))
4991+		return;
4992+
4993+	crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
4994+	if (WARN_ON(!crtc_state))
4995+		return;
4996+
4997+	mode = &crtc_state->adjusted_mode;
4998+
4999+	vic = drm_match_cea_mode(mode);
5000+
5001+	dev_dbg(priv->dev, "\"%s\" vic %d\n", mode->name, vic);
5002+
5003+	if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
5004+		ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
5005+		yuv420_mode = true;
5006+	} else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16) {
5007+		ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
5008+	}
5009+
5010+	/* VENC + VENC-DVI Mode setup */
5011+	meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
5012+
5013+	/* VCLK Set clock */
5014+	meson_encoder_hdmi_set_vclk(encoder_hdmi, mode);
5015+
5016+	if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
5017+		/* Setup YUV420 to HDMI-TX, no 10bit diphering */
5018+		writel_relaxed(2 | (2 << 2),
5019+			       priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
5020+	else if (encoder_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYVY8_1X16)
5021+		/* Setup YUV422 to HDMI-TX, no 10bit diphering */
5022+		writel_relaxed(1 | (2 << 2),
5023+				priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
5024+	else
5025+		/* Setup YUV444 to HDMI-TX, no 10bit diphering */
5026+		writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
5027+
5028+	dev_dbg(priv->dev, "%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
5029+
5030+	if (priv->venc.hdmi_use_enci)
5031+		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
5032+	else
5033+		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
5034+}
5035+
5036+static void meson_encoder_hdmi_atomic_disable(struct drm_bridge *bridge,
5037+					     struct drm_bridge_state *bridge_state)
5038+{
5039+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
5040+	struct meson_drm *priv = encoder_hdmi->priv;
5041+
5042+	writel_bits_relaxed(0x3, 0,
5043+			    priv->io_base + _REG(VPU_HDMI_SETTING));
5044+
5045+	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
5046+	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
5047+}
5048+
5049+static const u32 meson_encoder_hdmi_out_bus_fmts[] = {
5050+	MEDIA_BUS_FMT_YUV8_1X24,
5051+	MEDIA_BUS_FMT_UYVY8_1X16,
5052+	MEDIA_BUS_FMT_UYYVYY8_0_5X24,
5053+};
5054+
5055+static u32 *
5056+meson_encoder_hdmi_get_inp_bus_fmts(struct drm_bridge *bridge,
5057+					struct drm_bridge_state *bridge_state,
5058+					struct drm_crtc_state *crtc_state,
5059+					struct drm_connector_state *conn_state,
5060+					u32 output_fmt,
5061+					unsigned int *num_input_fmts)
5062+{
5063+	u32 *input_fmts = NULL;
5064+	int i;
5065+
5066+	*num_input_fmts = 0;
5067+
5068+	for (i = 0 ; i < ARRAY_SIZE(meson_encoder_hdmi_out_bus_fmts) ; ++i) {
5069+		if (output_fmt == meson_encoder_hdmi_out_bus_fmts[i]) {
5070+			*num_input_fmts = 1;
5071+			input_fmts = kcalloc(*num_input_fmts,
5072+					     sizeof(*input_fmts),
5073+					     GFP_KERNEL);
5074+			if (!input_fmts)
5075+				return NULL;
5076+
5077+			input_fmts[0] = output_fmt;
5078+
5079+			break;
5080+		}
5081+	}
5082+
5083+	return input_fmts;
5084+}
5085+
5086+static int meson_encoder_hdmi_atomic_check(struct drm_bridge *bridge,
5087+					struct drm_bridge_state *bridge_state,
5088+					struct drm_crtc_state *crtc_state,
5089+					struct drm_connector_state *conn_state)
5090+{
5091+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
5092+	struct drm_connector_state *old_conn_state =
5093+		drm_atomic_get_old_connector_state(conn_state->state, conn_state->connector);
5094+	struct meson_drm *priv = encoder_hdmi->priv;
5095+
5096+	encoder_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
5097+
5098+	dev_dbg(priv->dev, "output_bus_fmt %lx\n", encoder_hdmi->output_bus_fmt);
5099+
5100+	if (!drm_connector_atomic_hdr_metadata_equal(old_conn_state, conn_state))
5101+		crtc_state->mode_changed = true;
5102+
5103+	return 0;
5104+}
5105+
5106+static void meson_encoder_hdmi_hpd_notify(struct drm_bridge *bridge,
5107+					  enum drm_connector_status status)
5108+{
5109+	struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
5110+	struct edid *edid;
5111+
5112+	if (!encoder_hdmi->cec_notifier)
5113+		return;
5114+
5115+	if (status == connector_status_connected) {
5116+		edid = drm_bridge_get_edid(encoder_hdmi->next_bridge, encoder_hdmi->connector);
5117+		if (!edid)
5118+			return;
5119+
5120+		cec_notifier_set_phys_addr_from_edid(encoder_hdmi->cec_notifier, edid);
5121+	} else
5122+		cec_notifier_phys_addr_invalidate(encoder_hdmi->cec_notifier);
5123+}
5124+
5125+static const struct drm_bridge_funcs meson_encoder_hdmi_bridge_funcs = {
5126+	.attach = meson_encoder_hdmi_attach,
5127+	.detach = meson_encoder_hdmi_detach,
5128+	.mode_valid = meson_encoder_hdmi_mode_valid,
5129+	//.hpd_notify = meson_encoder_hdmi_hpd_notify, // UNIONMAN del
5130+	.atomic_enable = meson_encoder_hdmi_atomic_enable,
5131+	.atomic_disable = meson_encoder_hdmi_atomic_disable,
5132+	.atomic_get_input_bus_fmts = meson_encoder_hdmi_get_inp_bus_fmts,
5133+	.atomic_check = meson_encoder_hdmi_atomic_check,
5134+	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
5135+	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
5136+	.atomic_reset = drm_atomic_helper_bridge_reset,
5137+};
5138+
5139+int meson_encoder_hdmi_init(struct meson_drm *priv)
5140+{
5141+	struct meson_encoder_hdmi *meson_encoder_hdmi;
5142+	struct platform_device *pdev;
5143+	struct device_node *remote;
5144+	int ret;
5145+
5146+	meson_encoder_hdmi = devm_kzalloc(priv->dev, sizeof(*meson_encoder_hdmi), GFP_KERNEL);
5147+	if (!meson_encoder_hdmi)
5148+		return -ENOMEM;
5149+
5150+	/* HDMI Transceiver Bridge */
5151+	remote = of_graph_get_remote_node(priv->dev->of_node, 1, 0);
5152+	if (!remote) {
5153+		dev_err(priv->dev, "HDMI transceiver device is disabled");
5154+		return 0;
5155+	}
5156+
5157+	meson_encoder_hdmi->next_bridge = of_drm_find_bridge(remote);
5158+	if (!meson_encoder_hdmi->next_bridge) {
5159+		dev_err(priv->dev, "Failed to find HDMI transceiver bridge\n");
5160+		return -EPROBE_DEFER;
5161+	}
5162+
5163+	/* HDMI Encoder Bridge */
5164+	meson_encoder_hdmi->bridge.funcs = &meson_encoder_hdmi_bridge_funcs;
5165+	meson_encoder_hdmi->bridge.of_node = priv->dev->of_node;
5166+	meson_encoder_hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
5167+	meson_encoder_hdmi->bridge.interlace_allowed = true;
5168+
5169+	drm_bridge_add(&meson_encoder_hdmi->bridge);
5170+
5171+	meson_encoder_hdmi->priv = priv;
5172+
5173+	/* Encoder */
5174+	ret = drm_simple_encoder_init(priv->drm, &meson_encoder_hdmi->encoder,
5175+				      DRM_MODE_ENCODER_TMDS);
5176+	if (ret) {
5177+		dev_err(priv->dev, "Failed to init HDMI encoder: %d\n", ret);
5178+		return ret;
5179+	}
5180+
5181+	meson_encoder_hdmi->encoder.possible_crtcs = BIT(0);
5182+
5183+	/* Attach HDMI Encoder Bridge to Encoder */
5184+	ret = drm_bridge_attach(&meson_encoder_hdmi->encoder, &meson_encoder_hdmi->bridge, NULL,
5185+				0/*UNIONMAN modfiy: DRM_BRIDGE_ATTACH_NO_CONNECTOR*/);
5186+	if (ret) {
5187+		dev_err(priv->dev, "Failed to attach bridge: %d\n", ret);
5188+		return ret;
5189+	}
5190+
5191+#if 0 // UNIONMAN del: use connector created by dw_hdmi instead.
5192+	/* Initialize & attach Bridge Connector */
5193+	meson_encoder_hdmi->connector = drm_bridge_connector_init(priv->drm,
5194+							&meson_encoder_hdmi->encoder);
5195+	if (IS_ERR(meson_encoder_hdmi->connector)) {
5196+		dev_err(priv->dev, "Unable to create HDMI bridge connector\n");
5197+		return PTR_ERR(meson_encoder_hdmi->connector);
5198+	}
5199+	drm_connector_attach_encoder(meson_encoder_hdmi->connector,
5200+				     &meson_encoder_hdmi->encoder);
5201+
5202+	/*
5203+	 * We should have now in place:
5204+	 * encoder->[hdmi encoder bridge]->[dw-hdmi bridge]->[display connector bridge]->[display connector]
5205+	 */
5206+
5207+	/*
5208+	 * drm_connector_attach_max_bpc_property() requires the
5209+	 * connector to have a state.
5210+	 */
5211+	drm_atomic_helper_connector_reset(meson_encoder_hdmi->connector);
5212+
5213+	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
5214+	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
5215+	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
5216+		drm_connector_attach_hdr_output_metadata_property(meson_encoder_hdmi->connector);
5217+
5218+	drm_connector_attach_max_bpc_property(meson_encoder_hdmi->connector, 8, 8);
5219+
5220+	/* Handle this here until handled by drm_bridge_connector_init() */
5221+	meson_encoder_hdmi->connector->ycbcr_420_allowed = true;
5222+
5223+	pdev = of_find_device_by_node(remote);
5224+	if (pdev) {
5225+		struct cec_connector_info conn_info;
5226+		struct cec_notifier *notifier;
5227+
5228+		cec_fill_conn_info_from_drm(&conn_info, meson_encoder_hdmi->connector);
5229+
5230+		notifier = cec_notifier_conn_register(&pdev->dev, NULL, &conn_info);
5231+		if (!notifier)
5232+			return -ENOMEM;
5233+
5234+		meson_encoder_hdmi->cec_notifier = notifier;
5235+	}
5236+#endif
5237+	dev_dbg(priv->dev, "HDMI encoder initialized\n");
5238+
5239+	return 0;
5240+}
5241diff -Naur a/drivers/gpu/drm/meson/meson_encoder_hdmi.h b/drivers/gpu/drm/meson/meson_encoder_hdmi.h
5242--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.h	1970-01-01 08:00:00.000000000 +0800
5243+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.h	2023-02-23 17:02:04.959751069 +0800
5244@@ -0,0 +1,12 @@
5245+/* SPDX-License-Identifier: GPL-2.0-or-later */
5246+/*
5247+ * Copyright (C) 2021 BayLibre, SAS
5248+ * Author: Neil Armstrong <narmstrong@baylibre.com>
5249+ */
5250+
5251+#ifndef __MESON_ENCODER_HDMI_H
5252+#define __MESON_ENCODER_HDMI_H
5253+
5254+int meson_encoder_hdmi_init(struct meson_drm *priv);
5255+
5256+#endif /* __MESON_ENCODER_HDMI_H */
5257diff -Naur a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c
5258--- a/drivers/gpu/drm/meson/meson_overlay.c	2022-12-19 17:13:12.677518989 +0800
5259+++ b/drivers/gpu/drm/meson/meson_overlay.c	2023-02-23 17:02:04.959751069 +0800
5260@@ -10,10 +10,10 @@
5261 #include <drm/drm_atomic.h>
5262 #include <drm/drm_atomic_helper.h>
5263 #include <drm/drm_device.h>
5264+#include <drm/drm_fb_cma_helper.h>
5265 #include <drm/drm_fourcc.h>
5266-#include <drm/drm_plane_helper.h>
5267 #include <drm/drm_gem_cma_helper.h>
5268-#include <drm/drm_fb_cma_helper.h>
5269+#include <drm/drm_plane_helper.h>
5270 #include <drm/drm_gem_framebuffer_helper.h>
5271
5272 #include "meson_overlay.h"
5273@@ -167,16 +167,20 @@
5274 static int meson_overlay_atomic_check(struct drm_plane *plane,
5275 				      struct drm_plane_state *state)
5276 {
5277+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state->state,
5278+										 plane);
5279 	struct drm_crtc_state *crtc_state;
5280
5281-	if (!state->crtc)
5282+	if (!new_plane_state->crtc)
5283 		return 0;
5284
5285-	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
5286+	crtc_state = drm_atomic_get_crtc_state(state->state,
5287+					       new_plane_state->crtc);
5288 	if (IS_ERR(crtc_state))
5289 		return PTR_ERR(crtc_state);
5290
5291-	return drm_atomic_helper_check_plane_state(state, crtc_state,
5292+	return drm_atomic_helper_check_plane_state(new_plane_state,
5293+						   crtc_state,
5294 						   FRAC_16_16(1, 5),
5295 						   FRAC_16_16(5, 1),
5296 						   true, true);
5297@@ -464,11 +468,12 @@
5298 }
5299
5300 static void meson_overlay_atomic_update(struct drm_plane *plane,
5301-					struct drm_plane_state *old_state)
5302+					struct drm_plane_state *state)
5303 {
5304 	struct meson_overlay *meson_overlay = to_meson_overlay(plane);
5305-	struct drm_plane_state *state = plane->state;
5306-	struct drm_framebuffer *fb = state->fb;
5307+	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state->state,
5308+									   plane);
5309+	struct drm_framebuffer *fb = new_state->fb;
5310 	struct meson_drm *priv = meson_overlay->priv;
5311 	struct drm_gem_cma_object *gem;
5312 	unsigned long flags;
5313@@ -476,7 +481,7 @@
5314
5315 	DRM_DEBUG_DRIVER("\n");
5316
5317-	interlace_mode = state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE;
5318+	interlace_mode = new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE;
5319
5320 	spin_lock_irqsave(&priv->drm->event_lock, flags);
5321
5322@@ -717,7 +722,7 @@
5323 }
5324
5325 static void meson_overlay_atomic_disable(struct drm_plane *plane,
5326-				       struct drm_plane_state *old_state)
5327+				       struct drm_plane_state *state)
5328 {
5329 	struct meson_overlay *meson_overlay = to_meson_overlay(plane);
5330 	struct meson_drm *priv = meson_overlay->priv;
5331diff -Naur a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c
5332--- a/drivers/gpu/drm/meson/meson_plane.c	2022-12-19 17:13:12.677518989 +0800
5333+++ b/drivers/gpu/drm/meson/meson_plane.c	2023-02-23 17:02:04.959751069 +0800
5334@@ -73,12 +73,15 @@
5335 static int meson_plane_atomic_check(struct drm_plane *plane,
5336 				    struct drm_plane_state *state)
5337 {
5338+	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state->state,
5339+										 plane);
5340 	struct drm_crtc_state *crtc_state;
5341
5342-	if (!state->crtc)
5343+	if (!new_plane_state->crtc)
5344 		return 0;
5345
5346-	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
5347+	crtc_state = drm_atomic_get_crtc_state(state->state,
5348+					       new_plane_state->crtc);
5349 	if (IS_ERR(crtc_state))
5350 		return PTR_ERR(crtc_state);
5351
5352@@ -87,7 +90,8 @@
5353 	 * - Upscaling up to 5x, vertical and horizontal
5354 	 * - Final coordinates must match crtc size
5355 	 */
5356-	return drm_atomic_helper_check_plane_state(state, crtc_state,
5357+	return drm_atomic_helper_check_plane_state(new_plane_state,
5358+						   crtc_state,
5359 						   FRAC_16_16(1, 5),
5360 						   DRM_PLANE_HELPER_NO_SCALING,
5361 						   false, true);
5362@@ -126,13 +130,14 @@
5363 }
5364
5365 static void meson_plane_atomic_update(struct drm_plane *plane,
5366-				      struct drm_plane_state *old_state)
5367+				      struct drm_plane_state *state)
5368 {
5369 	struct meson_plane *meson_plane = to_meson_plane(plane);
5370-	struct drm_plane_state *state = plane->state;
5371-	struct drm_rect dest = drm_plane_state_dest(state);
5372+	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state->state,
5373+									   plane);
5374+	struct drm_rect dest = drm_plane_state_dest(new_state);
5375 	struct meson_drm *priv = meson_plane->priv;
5376-	struct drm_framebuffer *fb = state->fb;
5377+	struct drm_framebuffer *fb = new_state->fb;
5378 	struct drm_gem_cma_object *gem;
5379 	unsigned long flags;
5380 	int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
5381@@ -245,7 +250,7 @@
5382 	hf_bank_len = 4;
5383 	vf_bank_len = 4;
5384
5385-	if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
5386+	if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
5387 		vsc_bot_rcv_num = 6;
5388 		vsc_bot_rpt_p0_num = 2;
5389 	}
5390@@ -255,10 +260,10 @@
5391 	hsc_ini_rpt_p0_num = (hf_bank_len / 2) - 1;
5392 	vsc_ini_rpt_p0_num = (vf_bank_len / 2) - 1;
5393
5394-	src_w = fixed16_to_int(state->src_w);
5395-	src_h = fixed16_to_int(state->src_h);
5396-	dst_w = state->crtc_w;
5397-	dst_h = state->crtc_h;
5398+	src_w = fixed16_to_int(new_state->src_w);
5399+	src_h = fixed16_to_int(new_state->src_h);
5400+	dst_w = new_state->crtc_w;
5401+	dst_h = new_state->crtc_h;
5402
5403 	/*
5404 	 * When the output is interlaced, the OSD must switch between
5405@@ -267,7 +272,7 @@
5406 	 * But the vertical scaler can provide such funtionnality if
5407 	 * is configured for 2:1 scaling with interlace options enabled.
5408 	 */
5409-	if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
5410+	if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
5411 		dest.y1 /= 2;
5412 		dest.y2 /= 2;
5413 		dst_h /= 2;
5414@@ -276,7 +281,7 @@
5415 	hf_phase_step = ((src_w << 18) / dst_w) << 6;
5416 	vf_phase_step = (src_h << 20) / dst_h;
5417
5418-	if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
5419+	if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
5420 		bot_ini_phase = ((vf_phase_step / 2) >> 4);
5421 	else
5422 		bot_ini_phase = 0;
5423@@ -308,7 +313,7 @@
5424 					VSC_TOP_RPT_L0_NUM(vsc_ini_rpt_p0_num) |
5425 					VSC_VERTICAL_SCALER_EN;
5426
5427-		if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
5428+		if (new_state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
5429 			priv->viu.osd_sc_v_ctrl0 |=
5430 					VSC_BOT_INI_RCV_NUM(vsc_bot_rcv_num) |
5431 					VSC_BOT_RPT_L0_NUM(vsc_bot_rpt_p0_num) |
5432@@ -343,11 +348,11 @@
5433 	 * e.g. +30x1920 would be (1919 << 16) | 30
5434 	 */
5435 	priv->viu.osd1_blk0_cfg[1] =
5436-				((fixed16_to_int(state->src.x2) - 1) << 16) |
5437-				fixed16_to_int(state->src.x1);
5438+				((fixed16_to_int(new_state->src.x2) - 1) << 16) |
5439+				fixed16_to_int(new_state->src.x1);
5440 	priv->viu.osd1_blk0_cfg[2] =
5441-				((fixed16_to_int(state->src.y2) - 1) << 16) |
5442-				fixed16_to_int(state->src.y1);
5443+				((fixed16_to_int(new_state->src.y2) - 1) << 16) |
5444+				fixed16_to_int(new_state->src.y1);
5445 	priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
5446 	priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
5447
5448@@ -355,7 +360,6 @@
5449 		priv->viu.osd_blend_din0_scope_h = ((dest.x2 - 1) << 16) | dest.x1;
5450 		priv->viu.osd_blend_din0_scope_v = ((dest.y2 - 1) << 16) | dest.y1;
5451 		priv->viu.osb_blend0_size = dst_h << 16 | dst_w;
5452-		priv->viu.osb_blend1_size = dst_h << 16 | dst_w;
5453 	}
5454
5455 	/* Update Canvas with buffer address */
5456@@ -391,7 +395,7 @@
5457 }
5458
5459 static void meson_plane_atomic_disable(struct drm_plane *plane,
5460-				       struct drm_plane_state *old_state)
5461+				       struct drm_plane_state *state)
5462 {
5463 	struct meson_plane *meson_plane = to_meson_plane(plane);
5464 	struct meson_drm *priv = meson_plane->priv;
5465diff -Naur a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h
5466--- a/drivers/gpu/drm/meson/meson_registers.h	2022-12-19 17:13:12.677518989 +0800
5467+++ b/drivers/gpu/drm/meson/meson_registers.h	2023-02-23 17:02:04.959751069 +0800
5468@@ -812,6 +812,7 @@
5469 #define VENC_STATA 0x1b6d
5470 #define VENC_INTCTRL 0x1b6e
5471 #define		VENC_INTCTRL_ENCI_LNRST_INT_EN  BIT(1)
5472+#define		VENC_INTCTRL_ENCP_LNRST_INT_EN  BIT(9)
5473 #define VENC_INTFLAG 0x1b6f
5474 #define VENC_VIDEO_TST_EN 0x1b70
5475 #define VENC_VIDEO_TST_MDSEL 0x1b71
5476@@ -1192,7 +1193,11 @@
5477 #define ENCL_VIDEO_PB_OFFST 0x1ca5
5478 #define ENCL_VIDEO_PR_OFFST 0x1ca6
5479 #define ENCL_VIDEO_MODE 0x1ca7
5480+#define		ENCL_PX_LN_CNT_SHADOW_EN	BIT(15)
5481 #define ENCL_VIDEO_MODE_ADV 0x1ca8
5482+#define		ENCL_VIDEO_MODE_ADV_VFIFO_EN	BIT(3)
5483+#define		ENCL_VIDEO_MODE_ADV_GAIN_HDTV	BIT(4)
5484+#define		ENCL_SEL_GAMMA_RGB_IN		BIT(10)
5485 #define ENCL_DBG_PX_RST 0x1ca9
5486 #define ENCL_DBG_LN_RST 0x1caa
5487 #define ENCL_DBG_PX_INT 0x1cab
5488@@ -1219,11 +1224,14 @@
5489 #define ENCL_VIDEO_VOFFST 0x1cc0
5490 #define ENCL_VIDEO_RGB_CTRL 0x1cc1
5491 #define ENCL_VIDEO_FILT_CTRL 0x1cc2
5492+#define		ENCL_VIDEO_FILT_CTRL_BYPASS_FILTER	BIT(12)
5493 #define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
5494 #define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
5495 #define ENCL_VIDEO_MATRIX_CB 0x1cc5
5496 #define ENCL_VIDEO_MATRIX_CR 0x1cc6
5497 #define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
5498+#define		ENCL_VIDEO_RGBIN_RGB	BIT(0)
5499+#define		ENCL_VIDEO_RGBIN_ZBLK	BIT(1)
5500 #define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
5501 #define ENCL_DACSEL_0 0x1cc9
5502 #define ENCL_DACSEL_1 0x1cca
5503@@ -1300,13 +1308,28 @@
5504 #define RDMA_STATUS2 0x1116
5505 #define RDMA_STATUS3 0x1117
5506 #define L_GAMMA_CNTL_PORT 0x1400
5507+#define		L_GAMMA_CNTL_PORT_VCOM_POL	BIT(7)	/* RW */
5508+#define		L_GAMMA_CNTL_PORT_RVS_OUT	BIT(6)	/* RW */
5509+#define		L_GAMMA_CNTL_PORT_ADR_RDY	BIT(5)	/* Read Only */
5510+#define		L_GAMMA_CNTL_PORT_WR_RDY	BIT(4)	/* Read Only */
5511+#define		L_GAMMA_CNTL_PORT_RD_RDY	BIT(3)	/* Read Only */
5512+#define		L_GAMMA_CNTL_PORT_TR		BIT(2)	/* RW */
5513+#define		L_GAMMA_CNTL_PORT_SET		BIT(1)	/* RW */
5514+#define		L_GAMMA_CNTL_PORT_EN		BIT(0)	/* RW */
5515 #define L_GAMMA_DATA_PORT 0x1401
5516 #define L_GAMMA_ADDR_PORT 0x1402
5517+#define		L_GAMMA_ADDR_PORT_RD		BIT(12)
5518+#define		L_GAMMA_ADDR_PORT_AUTO_INC	BIT(11)
5519+#define		L_GAMMA_ADDR_PORT_SEL_R		BIT(10)
5520+#define		L_GAMMA_ADDR_PORT_SEL_G		BIT(9)
5521+#define		L_GAMMA_ADDR_PORT_SEL_B		BIT(8)
5522+#define		L_GAMMA_ADDR_PORT_ADDR		GENMASK(7, 0)
5523 #define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
5524 #define L_RGB_BASE_ADDR 0x1405
5525 #define L_RGB_COEFF_ADDR 0x1406
5526 #define L_POL_CNTL_ADDR 0x1407
5527 #define L_DITH_CNTL_ADDR 0x1408
5528+#define		L_DITH_CNTL_DITH10_EN	BIT(10)
5529 #define L_GAMMA_PROBE_CTRL 0x1409
5530 #define L_GAMMA_PROBE_COLOR_L 0x140a
5531 #define L_GAMMA_PROBE_COLOR_H 0x140b
5532@@ -1363,6 +1386,8 @@
5533 #define L_LCD_PWM1_HI_ADDR 0x143f
5534 #define L_INV_CNT_ADDR 0x1440
5535 #define L_TCON_MISC_SEL_ADDR 0x1441
5536+#define		L_TCON_MISC_SEL_STV1	BIT(4)
5537+#define		L_TCON_MISC_SEL_STV2	BIT(5)
5538 #define L_DUAL_PORT_CNTL_ADDR 0x1442
5539 #define MLVDS_CLK_CTL1_HI 0x1443
5540 #define MLVDS_CLK_CTL1_LO 0x1444
5541diff -Naur a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
5542--- a/drivers/gpu/drm/meson/meson_vclk.c	2022-12-19 17:13:12.677518989 +0800
5543+++ b/drivers/gpu/drm/meson/meson_vclk.c	2023-02-23 17:02:04.959751069 +0800
5544@@ -55,6 +55,8 @@
5545 #define VCLK2_DIV_MASK		0xff
5546 #define VCLK2_DIV_EN		BIT(16)
5547 #define VCLK2_DIV_RESET		BIT(17)
5548+#define CTS_ENCL_SEL_MASK	(0xf << 12)
5549+#define CTS_ENCL_SEL_SHIFT	12
5550 #define CTS_VDAC_SEL_MASK	(0xf << 28)
5551 #define CTS_VDAC_SEL_SHIFT	28
5552 #define HHI_VIID_CLK_CNTL	0x12c /* 0x4b offset in data sheet */
5553@@ -83,6 +85,7 @@
5554 #define VCLK_DIV12_EN		BIT(4)
5555 #define HHI_VID_CLK_CNTL2	0x194 /* 0x65 offset in data sheet */
5556 #define CTS_ENCI_EN		BIT(0)
5557+#define CTS_ENCL_EN		BIT(3)
5558 #define CTS_ENCP_EN		BIT(2)
5559 #define CTS_VDAC_EN		BIT(4)
5560 #define HDMI_TX_PIXEL_EN	BIT(5)
5561@@ -131,7 +134,7 @@
5562 	VID_PLL_DIV_15,
5563 };
5564
5565-void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
5566+static void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
5567 {
5568 	unsigned int shift_val = 0;
5569 	unsigned int shift_sel = 0;
5570@@ -357,6 +360,8 @@
5571 	MESON_VCLK_HDMI_594000,
5572 /* 2970 /1 /1 /1 /5 /1  => /1 /2 */
5573 	MESON_VCLK_HDMI_594000_YUV420,
5574+/* 4830 /2 /1 /2 /5 /1  => /1 /1 */
5575+	MESON_VCLK_HDMI_241500,
5576 };
5577
5578 struct meson_vclk_params {
5579@@ -467,6 +472,18 @@
5580 		.vid_pll_div = VID_PLL_DIV_5,
5581 		.vclk_div = 1,
5582 	},
5583+	[MESON_VCLK_HDMI_241500] = {
5584+		.pll_freq = 4830000,
5585+		.phy_freq = 2415000,
5586+		.venc_freq = 241500,
5587+		.vclk_freq = 241500,
5588+		.pixel_freq = 241500,
5589+		.pll_od1 = 2,
5590+		.pll_od2 = 1,
5591+		.pll_od3 = 2,
5592+		.vid_pll_div = VID_PLL_DIV_5,
5593+		.vclk_div = 1,
5594+	},
5595 	{ /* sentinel */ },
5596 };
5597
5598@@ -487,9 +504,9 @@
5599 	return 0;
5600 }
5601
5602-void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
5603-			       unsigned int frac, unsigned int od1,
5604-			       unsigned int od2, unsigned int od3)
5605+static void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
5606+				      unsigned int frac, unsigned int od1,
5607+				      unsigned int od2, unsigned int od3)
5608 {
5609 	unsigned int val;
5610
5611@@ -873,6 +890,10 @@
5612 			m = 0xf7;
5613 			frac = vic_alternate_clock ? 0x8148 : 0x10000;
5614 			break;
5615+		case 4830000:
5616+			m = 0xc9;
5617+			frac = 0xd560;
5618+			break;
5619 		}
5620
5621 		meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
5622@@ -1024,6 +1045,47 @@
5623 	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
5624 }
5625
5626+static void meson_dsi_clock_config(struct meson_drm *priv, unsigned int freq)
5627+{
5628+	meson_hdmi_pll_generic_set(priv, freq * 10);
5629+
5630+	/* Setup vid_pll divider value /5 */
5631+	meson_vid_pll_set(priv, VID_PLL_DIV_5);
5632+
5633+	/* Disable VCLK2 */
5634+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
5635+
5636+	/* Setup the VCLK2 divider value /2 */
5637+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV, VCLK2_DIV_MASK, 2 - 1);
5638+
5639+	/* select vid_pll for vclk2 */
5640+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
5641+			   VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
5642+
5643+	/* enable vclk2 gate */
5644+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
5645+
5646+	/* select vclk2_div1 for encl */
5647+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
5648+			   CTS_ENCL_SEL_MASK, (8 << CTS_ENCL_SEL_SHIFT));
5649+
5650+	/* release vclk2_div_reset and enable vclk2_div */
5651+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV, VCLK2_DIV_EN | VCLK2_DIV_RESET,
5652+			   VCLK2_DIV_EN);
5653+
5654+	/* enable vclk2_div1 gate */
5655+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_DIV1_EN, VCLK2_DIV1_EN);
5656+
5657+	/* reset vclk2 */
5658+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
5659+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_SOFT_RESET, 0);
5660+
5661+	/* enable encl_clk */
5662+	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2, CTS_ENCL_EN, CTS_ENCL_EN);
5663+
5664+	usleep_range(10000, 11000);
5665+}
5666+
5667 void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
5668 		      unsigned int phy_freq, unsigned int vclk_freq,
5669 		      unsigned int venc_freq, unsigned int dac_freq,
5670@@ -1050,6 +1112,9 @@
5671 		meson_vclk_set(priv, phy_freq, 0, 0, 0,
5672 			       VID_PLL_DIV_5, 2, 1, 1, false, false);
5673 		return;
5674+	} else if (target == MESON_VCLK_TARGET_DSI) {
5675+		meson_dsi_clock_config(priv, phy_freq);
5676+		return;
5677 	}
5678
5679 	hdmi_tx_div = vclk_freq / dac_freq;
5680diff -Naur a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
5681--- a/drivers/gpu/drm/meson/meson_vclk.h	2022-12-19 17:13:12.677518989 +0800
5682+++ b/drivers/gpu/drm/meson/meson_vclk.h	2023-02-23 17:02:04.959751069 +0800
5683@@ -17,6 +17,7 @@
5684 	MESON_VCLK_TARGET_CVBS = 0,
5685 	MESON_VCLK_TARGET_HDMI = 1,
5686 	MESON_VCLK_TARGET_DMT = 2,
5687+	MESON_VCLK_TARGET_DSI = 3,
5688 };
5689
5690 /* 27MHz is the CVBS Pixel Clock */
5691diff -Naur a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
5692--- a/drivers/gpu/drm/meson/meson_venc.c	2022-12-19 17:13:12.677518989 +0800
5693+++ b/drivers/gpu/drm/meson/meson_venc.c	2023-02-23 17:02:04.959751069 +0800
5694@@ -6,6 +6,7 @@
5695  */
5696
5697 #include <linux/export.h>
5698+#include <linux/iopoll.h>
5699
5700 #include <drm/drm_modes.h>
5701
5702@@ -45,7 +46,7 @@
5703  * The ENCI is designed for PAl or NTSC encoding and can go through the VDAC
5704  * directly for CVBS encoding or through the ENCI_DVI encoder for HDMI.
5705  * The ENCP is designed for Progressive encoding but can also generate
5706- * 1080i interlaced pixels, and was initialy desined to encode pixels for
5707+ * 1080i interlaced pixels, and was initially designed to encode pixels for
5708  * VDAC to output RGB ou YUV analog outputs.
5709  * It's output is only used through the ENCP_DVI encoder for HDMI.
5710  * The ENCL LVDS encoder is not implemented.
5711@@ -866,10 +867,11 @@
5712 			    DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
5713 		return MODE_BAD;
5714
5715-	if (mode->hdisplay < 640 || mode->hdisplay > 1920)
5716+	/* support higher resolution than 1920x1080 */
5717+	if (mode->hdisplay < 640 || mode->hdisplay > 2560)
5718 		return MODE_BAD_HVALUE;
5719
5720-	if (mode->vdisplay < 480 || mode->vdisplay > 1200)
5721+	if (mode->vdisplay < 480 || mode->vdisplay > 1600)
5722 		return MODE_BAD_VVALUE;
5723
5724 	return MODE_OK;
5725@@ -890,8 +892,8 @@
5726 }
5727 EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
5728
5729-void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
5730-				   union meson_hdmi_venc_mode *dmt_mode)
5731+static void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
5732+					  union meson_hdmi_venc_mode *dmt_mode)
5733 {
5734 	memset(dmt_mode, 0, sizeof(*dmt_mode));
5735
5736@@ -1557,6 +1559,205 @@
5737 }
5738 EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
5739
5740+static unsigned short meson_encl_gamma_table[256] = {
5741+	0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60,
5742+	64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124,
5743+	128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188,
5744+	192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252,
5745+	256, 260, 264, 268, 272, 276, 280, 284, 288, 292, 296, 300, 304, 308, 312, 316,
5746+	320, 324, 328, 332, 336, 340, 344, 348, 352, 356, 360, 364, 368, 372, 376, 380,
5747+	384, 388, 392, 396, 400, 404, 408, 412, 416, 420, 424, 428, 432, 436, 440, 444,
5748+	448, 452, 456, 460, 464, 468, 472, 476, 480, 484, 488, 492, 496, 500, 504, 508,
5749+	512, 516, 520, 524, 528, 532, 536, 540, 544, 548, 552, 556, 560, 564, 568, 572,
5750+	576, 580, 584, 588, 592, 596, 600, 604, 608, 612, 616, 620, 624, 628, 632, 636,
5751+	640, 644, 648, 652, 656, 660, 664, 668, 672, 676, 680, 684, 688, 692, 696, 700,
5752+	704, 708, 712, 716, 720, 724, 728, 732, 736, 740, 744, 748, 752, 756, 760, 764,
5753+	768, 772, 776, 780, 784, 788, 792, 796, 800, 804, 808, 812, 816, 820, 824, 828,
5754+	832, 836, 840, 844, 848, 852, 856, 860, 864, 868, 872, 876, 880, 884, 888, 892,
5755+	896, 900, 904, 908, 912, 916, 920, 924, 928, 932, 936, 940, 944, 948, 952, 956,
5756+	960, 964, 968, 972, 976, 980, 984, 988, 992, 996, 1000, 1004, 1008, 1012, 1016, 1020,
5757+};
5758+
5759+static void meson_encl_set_gamma_table(struct meson_drm *priv, u16 *data,
5760+				       u32 rgb_mask)
5761+{
5762+	int i, ret;
5763+	u32 reg;
5764+
5765+	writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, 0,
5766+			    priv->io_base + _REG(L_GAMMA_CNTL_PORT));
5767+
5768+	ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT),
5769+					 reg, reg & L_GAMMA_CNTL_PORT_ADR_RDY, 10, 10000);
5770+	if (ret)
5771+		pr_warn("%s: GAMMA ADR_RDY timeout\n", __func__);
5772+
5773+	writel_relaxed(L_GAMMA_ADDR_PORT_AUTO_INC | rgb_mask |
5774+		       FIELD_PREP(L_GAMMA_ADDR_PORT_ADDR, 0),
5775+		       priv->io_base + _REG(L_GAMMA_ADDR_PORT));
5776+
5777+	for (i = 0; i < 256; i++) {
5778+		ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT),
5779+						 reg, reg & L_GAMMA_CNTL_PORT_WR_RDY,
5780+						 10, 10000);
5781+		if (ret)
5782+			pr_warn_once("%s: GAMMA WR_RDY timeout\n", __func__);
5783+
5784+		writel_relaxed(data[i], priv->io_base + _REG(L_GAMMA_DATA_PORT));
5785+	}
5786+
5787+	ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT),
5788+					 reg, reg & L_GAMMA_CNTL_PORT_ADR_RDY, 10, 10000);
5789+	if (ret)
5790+		pr_warn("%s: GAMMA ADR_RDY timeout\n", __func__);
5791+
5792+	writel_relaxed(L_GAMMA_ADDR_PORT_AUTO_INC | rgb_mask |
5793+		       FIELD_PREP(L_GAMMA_ADDR_PORT_ADDR, 0x23),
5794+		       priv->io_base + _REG(L_GAMMA_ADDR_PORT));
5795+}
5796+
5797+void meson_encl_load_gamma(struct meson_drm *priv)
5798+{
5799+	meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_R);
5800+	meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_G);
5801+	meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_B);
5802+
5803+	writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, L_GAMMA_CNTL_PORT_EN,
5804+			    priv->io_base + _REG(L_GAMMA_CNTL_PORT));
5805+}
5806+
5807+void meson_venc_mipi_dsi_mode_set(struct meson_drm *priv,
5808+				  const struct drm_display_mode *mode)
5809+{
5810+	unsigned int max_pxcnt;
5811+	unsigned int max_lncnt;
5812+	unsigned int havon_begin;
5813+	unsigned int havon_end;
5814+	unsigned int vavon_bline;
5815+	unsigned int vavon_eline;
5816+	unsigned int hso_begin;
5817+	unsigned int hso_end;
5818+	unsigned int vso_begin;
5819+	unsigned int vso_end;
5820+	unsigned int vso_bline;
5821+	unsigned int vso_eline;
5822+
5823+	max_pxcnt = mode->htotal - 1;
5824+	max_lncnt = mode->vtotal - 1;
5825+	havon_begin = mode->htotal - mode->hsync_start;
5826+	havon_end = havon_begin + mode->hdisplay - 1;
5827+	vavon_bline = mode->vtotal - mode->vsync_start;
5828+	vavon_eline = vavon_bline + mode->vdisplay - 1;
5829+	hso_begin = 0;
5830+	hso_end = mode->hsync_end - mode->hsync_start;
5831+	vso_begin = 0;
5832+	vso_end = 0;
5833+	vso_bline = 0;
5834+	vso_eline = mode->vsync_end - mode->vsync_start;
5835+
5836+	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCL);
5837+
5838+	writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
5839+
5840+	writel_relaxed(ENCL_PX_LN_CNT_SHADOW_EN, priv->io_base + _REG(ENCL_VIDEO_MODE));
5841+	writel_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN |
5842+		       ENCL_VIDEO_MODE_ADV_GAIN_HDTV |
5843+		       ENCL_SEL_GAMMA_RGB_IN, priv->io_base + _REG(ENCL_VIDEO_MODE_ADV));
5844+
5845+	writel_relaxed(ENCL_VIDEO_FILT_CTRL_BYPASS_FILTER,
5846+		       priv->io_base + _REG(ENCL_VIDEO_FILT_CTRL));
5847+	writel_relaxed(max_pxcnt, priv->io_base + _REG(ENCL_VIDEO_MAX_PXCNT));
5848+	writel_relaxed(max_lncnt, priv->io_base + _REG(ENCL_VIDEO_MAX_LNCNT));
5849+	writel_relaxed(havon_begin, priv->io_base + _REG(ENCL_VIDEO_HAVON_BEGIN));
5850+	writel_relaxed(havon_end, priv->io_base + _REG(ENCL_VIDEO_HAVON_END));
5851+	writel_relaxed(vavon_bline, priv->io_base + _REG(ENCL_VIDEO_VAVON_BLINE));
5852+	writel_relaxed(vavon_eline, priv->io_base + _REG(ENCL_VIDEO_VAVON_ELINE));
5853+
5854+	writel_relaxed(hso_begin, priv->io_base + _REG(ENCL_VIDEO_HSO_BEGIN));
5855+	writel_relaxed(hso_end, priv->io_base + _REG(ENCL_VIDEO_HSO_END));
5856+	writel_relaxed(vso_begin, priv->io_base + _REG(ENCL_VIDEO_VSO_BEGIN));
5857+	writel_relaxed(vso_end, priv->io_base + _REG(ENCL_VIDEO_VSO_END));
5858+	writel_relaxed(vso_bline, priv->io_base + _REG(ENCL_VIDEO_VSO_BLINE));
5859+	writel_relaxed(vso_eline, priv->io_base + _REG(ENCL_VIDEO_VSO_ELINE));
5860+	writel_relaxed(ENCL_VIDEO_RGBIN_RGB | ENCL_VIDEO_RGBIN_ZBLK,
5861+		       priv->io_base + _REG(ENCL_VIDEO_RGBIN_CTRL));
5862+
5863+	/* default black pattern */
5864+	writel_relaxed(0, priv->io_base + _REG(ENCL_TST_MDSEL));
5865+	writel_relaxed(0, priv->io_base + _REG(ENCL_TST_Y));
5866+	writel_relaxed(0, priv->io_base + _REG(ENCL_TST_CB));
5867+	writel_relaxed(0, priv->io_base + _REG(ENCL_TST_CR));
5868+	writel_relaxed(1, priv->io_base + _REG(ENCL_TST_EN));
5869+	writel_bits_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN, 0,
5870+			    priv->io_base + _REG(ENCL_VIDEO_MODE_ADV));
5871+
5872+	writel_relaxed(1, priv->io_base + _REG(ENCL_VIDEO_EN));
5873+
5874+	writel_relaxed(0, priv->io_base + _REG(L_RGB_BASE_ADDR));
5875+	writel_relaxed(0x400, priv->io_base + _REG(L_RGB_COEFF_ADDR)); /* Magic value */
5876+
5877+	writel_relaxed(L_DITH_CNTL_DITH10_EN, priv->io_base + _REG(L_DITH_CNTL_ADDR));
5878+
5879+	/* DE signal for TTL */
5880+	writel_relaxed(havon_begin, priv->io_base + _REG(L_OEH_HS_ADDR));
5881+	writel_relaxed(havon_end + 1, priv->io_base + _REG(L_OEH_HE_ADDR));
5882+	writel_relaxed(vavon_bline, priv->io_base + _REG(L_OEH_VS_ADDR));
5883+	writel_relaxed(vavon_eline, priv->io_base + _REG(L_OEH_VE_ADDR));
5884+
5885+	/* DE signal for TTL */
5886+	writel_relaxed(havon_begin, priv->io_base + _REG(L_OEV1_HS_ADDR));
5887+	writel_relaxed(havon_end + 1, priv->io_base + _REG(L_OEV1_HE_ADDR));
5888+	writel_relaxed(vavon_bline, priv->io_base + _REG(L_OEV1_VS_ADDR));
5889+	writel_relaxed(vavon_eline, priv->io_base + _REG(L_OEV1_VE_ADDR));
5890+
5891+	/* Hsync signal for TTL */
5892+	if (mode->flags & DRM_MODE_FLAG_PHSYNC) {
5893+		writel_relaxed(hso_end, priv->io_base + _REG(L_STH1_HS_ADDR));
5894+		writel_relaxed(hso_begin, priv->io_base + _REG(L_STH1_HE_ADDR));
5895+	} else {
5896+		writel_relaxed(hso_begin, priv->io_base + _REG(L_STH1_HS_ADDR));
5897+		writel_relaxed(hso_end, priv->io_base + _REG(L_STH1_HE_ADDR));
5898+	}
5899+	writel_relaxed(0, priv->io_base + _REG(L_STH1_VS_ADDR));
5900+	writel_relaxed(max_lncnt, priv->io_base + _REG(L_STH1_VE_ADDR));
5901+
5902+	/* Vsync signal for TTL */
5903+	writel_relaxed(vso_begin, priv->io_base + _REG(L_STV1_HS_ADDR));
5904+	writel_relaxed(vso_end, priv->io_base + _REG(L_STV1_HE_ADDR));
5905+	if (mode->flags & DRM_MODE_FLAG_PVSYNC) {
5906+		writel_relaxed(vso_eline, priv->io_base + _REG(L_STV1_VS_ADDR));
5907+		writel_relaxed(vso_bline, priv->io_base + _REG(L_STV1_VE_ADDR));
5908+	} else {
5909+		writel_relaxed(vso_bline, priv->io_base + _REG(L_STV1_VS_ADDR));
5910+		writel_relaxed(vso_eline, priv->io_base + _REG(L_STV1_VE_ADDR));
5911+	}
5912+
5913+	/* DE signal */
5914+	writel_relaxed(havon_begin, priv->io_base + _REG(L_DE_HS_ADDR));
5915+	writel_relaxed(havon_end + 1, priv->io_base + _REG(L_DE_HE_ADDR));
5916+	writel_relaxed(vavon_bline, priv->io_base + _REG(L_DE_VS_ADDR));
5917+	writel_relaxed(vavon_eline, priv->io_base + _REG(L_DE_VE_ADDR));
5918+
5919+	/* Hsync signal */
5920+	writel_relaxed(hso_begin, priv->io_base + _REG(L_HSYNC_HS_ADDR));
5921+	writel_relaxed(hso_end, priv->io_base + _REG(L_HSYNC_HE_ADDR));
5922+	writel_relaxed(0, priv->io_base + _REG(L_HSYNC_VS_ADDR));
5923+	writel_relaxed(max_lncnt, priv->io_base + _REG(L_HSYNC_VE_ADDR));
5924+
5925+	/* Vsync signal */
5926+	writel_relaxed(vso_begin, priv->io_base + _REG(L_VSYNC_HS_ADDR));
5927+	writel_relaxed(vso_end, priv->io_base + _REG(L_VSYNC_HE_ADDR));
5928+	writel_relaxed(vso_bline, priv->io_base + _REG(L_VSYNC_VS_ADDR));
5929+	writel_relaxed(vso_eline, priv->io_base + _REG(L_VSYNC_VE_ADDR));
5930+
5931+	writel_relaxed(0, priv->io_base + _REG(L_INV_CNT_ADDR));
5932+	writel_relaxed(L_TCON_MISC_SEL_STV1 | L_TCON_MISC_SEL_STV2,
5933+		       priv->io_base + _REG(L_TCON_MISC_SEL_ADDR));
5934+
5935+	priv->venc.current_mode = MESON_VENC_MODE_MIPI_DSI;
5936+}
5937+EXPORT_SYMBOL_GPL(meson_venc_mipi_dsi_mode_set);
5938+
5939 void meson_venci_cvbs_mode_set(struct meson_drm *priv,
5940 			       struct meson_cvbs_enci_mode *mode)
5941 {
5942@@ -1747,8 +1948,15 @@
5943
5944 void meson_venc_enable_vsync(struct meson_drm *priv)
5945 {
5946-	writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
5947-		       priv->io_base + _REG(VENC_INTCTRL));
5948+	switch (priv->venc.current_mode) {
5949+	case MESON_VENC_MODE_MIPI_DSI:
5950+		writel_relaxed(VENC_INTCTRL_ENCP_LNRST_INT_EN,
5951+			       priv->io_base + _REG(VENC_INTCTRL));
5952+		break;
5953+	default:
5954+		writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
5955+			       priv->io_base + _REG(VENC_INTCTRL));
5956+	}
5957 	regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
5958 }
5959
5960diff -Naur a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c
5961--- a/drivers/gpu/drm/meson/meson_venc_cvbs.c	2022-12-19 17:13:12.677518989 +0800
5962+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c	1970-01-01 08:00:00.000000000 +0800
5963@@ -1,293 +0,0 @@
5964-// SPDX-License-Identifier: GPL-2.0-or-later
5965-/*
5966- * Copyright (C) 2016 BayLibre, SAS
5967- * Author: Neil Armstrong <narmstrong@baylibre.com>
5968- * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5969- * Copyright (C) 2014 Endless Mobile
5970- *
5971- * Written by:
5972- *     Jasper St. Pierre <jstpierre@mecheye.net>
5973- */
5974-
5975-#include <linux/export.h>
5976-#include <linux/of_graph.h>
5977-
5978-#include <drm/drm_atomic_helper.h>
5979-#include <drm/drm_device.h>
5980-#include <drm/drm_edid.h>
5981-#include <drm/drm_probe_helper.h>
5982-#include <drm/drm_print.h>
5983-
5984-#include "meson_registers.h"
5985-#include "meson_vclk.h"
5986-#include "meson_venc_cvbs.h"
5987-
5988-/* HHI VDAC Registers */
5989-#define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
5990-#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbd offset in data sheet */
5991-#define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
5992-#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbe offset in data sheet */
5993-
5994-struct meson_venc_cvbs {
5995-	struct drm_encoder	encoder;
5996-	struct drm_connector	connector;
5997-	struct meson_drm	*priv;
5998-};
5999-#define encoder_to_meson_venc_cvbs(x) \
6000-	container_of(x, struct meson_venc_cvbs, encoder)
6001-
6002-#define connector_to_meson_venc_cvbs(x) \
6003-	container_of(x, struct meson_venc_cvbs, connector)
6004-
6005-/* Supported Modes */
6006-
6007-struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
6008-	{ /* PAL */
6009-		.enci = &meson_cvbs_enci_pal,
6010-		.mode = {
6011-			DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
6012-				 720, 732, 795, 864, 0, 576, 580, 586, 625, 0,
6013-				 DRM_MODE_FLAG_INTERLACE),
6014-			.picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
6015-		},
6016-	},
6017-	{ /* NTSC */
6018-		.enci = &meson_cvbs_enci_ntsc,
6019-		.mode = {
6020-			DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
6021-				720, 739, 801, 858, 0, 480, 488, 494, 525, 0,
6022-				DRM_MODE_FLAG_INTERLACE),
6023-			.picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
6024-		},
6025-	},
6026-};
6027-
6028-static const struct meson_cvbs_mode *
6029-meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
6030-{
6031-	int i;
6032-
6033-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
6034-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
6035-
6036-		if (drm_mode_match(req_mode, &meson_mode->mode,
6037-				   DRM_MODE_MATCH_TIMINGS |
6038-				   DRM_MODE_MATCH_CLOCK |
6039-				   DRM_MODE_MATCH_FLAGS |
6040-				   DRM_MODE_MATCH_3D_FLAGS))
6041-			return meson_mode;
6042-	}
6043-
6044-	return NULL;
6045-}
6046-
6047-/* Connector */
6048-
6049-static void meson_cvbs_connector_destroy(struct drm_connector *connector)
6050-{
6051-	drm_connector_cleanup(connector);
6052-}
6053-
6054-static enum drm_connector_status
6055-meson_cvbs_connector_detect(struct drm_connector *connector, bool force)
6056-{
6057-	/* FIXME: Add load-detect or jack-detect if possible */
6058-	return connector_status_connected;
6059-}
6060-
6061-static int meson_cvbs_connector_get_modes(struct drm_connector *connector)
6062-{
6063-	struct drm_device *dev = connector->dev;
6064-	struct drm_display_mode *mode;
6065-	int i;
6066-
6067-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
6068-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
6069-
6070-		mode = drm_mode_duplicate(dev, &meson_mode->mode);
6071-		if (!mode) {
6072-			DRM_ERROR("Failed to create a new display mode\n");
6073-			return 0;
6074-		}
6075-
6076-		drm_mode_probed_add(connector, mode);
6077-	}
6078-
6079-	return i;
6080-}
6081-
6082-static int meson_cvbs_connector_mode_valid(struct drm_connector *connector,
6083-					   struct drm_display_mode *mode)
6084-{
6085-	/* Validate the modes added in get_modes */
6086-	return MODE_OK;
6087-}
6088-
6089-static const struct drm_connector_funcs meson_cvbs_connector_funcs = {
6090-	.detect			= meson_cvbs_connector_detect,
6091-	.fill_modes		= drm_helper_probe_single_connector_modes,
6092-	.destroy		= meson_cvbs_connector_destroy,
6093-	.reset			= drm_atomic_helper_connector_reset,
6094-	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
6095-	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
6096-};
6097-
6098-static const
6099-struct drm_connector_helper_funcs meson_cvbs_connector_helper_funcs = {
6100-	.get_modes	= meson_cvbs_connector_get_modes,
6101-	.mode_valid	= meson_cvbs_connector_mode_valid,
6102-};
6103-
6104-/* Encoder */
6105-
6106-static void meson_venc_cvbs_encoder_destroy(struct drm_encoder *encoder)
6107-{
6108-	drm_encoder_cleanup(encoder);
6109-}
6110-
6111-static const struct drm_encoder_funcs meson_venc_cvbs_encoder_funcs = {
6112-	.destroy        = meson_venc_cvbs_encoder_destroy,
6113-};
6114-
6115-static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
6116-					struct drm_crtc_state *crtc_state,
6117-					struct drm_connector_state *conn_state)
6118-{
6119-	if (meson_cvbs_get_mode(&crtc_state->mode))
6120-		return 0;
6121-
6122-	return -EINVAL;
6123-}
6124-
6125-static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
6126-{
6127-	struct meson_venc_cvbs *meson_venc_cvbs =
6128-					encoder_to_meson_venc_cvbs(encoder);
6129-	struct meson_drm *priv = meson_venc_cvbs->priv;
6130-
6131-	/* Disable CVBS VDAC */
6132-	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
6133-		regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
6134-		regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
6135-	} else {
6136-		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
6137-		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
6138-	}
6139-}
6140-
6141-static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
6142-{
6143-	struct meson_venc_cvbs *meson_venc_cvbs =
6144-					encoder_to_meson_venc_cvbs(encoder);
6145-	struct meson_drm *priv = meson_venc_cvbs->priv;
6146-
6147-	/* VDAC0 source is not from ATV */
6148-	writel_bits_relaxed(VENC_VDAC_SEL_ATV_DMD, 0,
6149-			    priv->io_base + _REG(VENC_VDAC_DACSEL0));
6150-
6151-	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
6152-		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
6153-		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
6154-	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
6155-		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
6156-		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
6157-		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
6158-	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
6159-		regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0x906001);
6160-		regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 0);
6161-	}
6162-}
6163-
6164-static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
6165-				   struct drm_display_mode *mode,
6166-				   struct drm_display_mode *adjusted_mode)
6167-{
6168-	const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode);
6169-	struct meson_venc_cvbs *meson_venc_cvbs =
6170-					encoder_to_meson_venc_cvbs(encoder);
6171-	struct meson_drm *priv = meson_venc_cvbs->priv;
6172-
6173-	if (meson_mode) {
6174-		meson_venci_cvbs_mode_set(priv, meson_mode->enci);
6175-
6176-		/* Setup 27MHz vclk2 for ENCI and VDAC */
6177-		meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
6178-				 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
6179-				 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
6180-				 true);
6181-	}
6182-}
6183-
6184-static const struct drm_encoder_helper_funcs
6185-				meson_venc_cvbs_encoder_helper_funcs = {
6186-	.atomic_check	= meson_venc_cvbs_encoder_atomic_check,
6187-	.disable	= meson_venc_cvbs_encoder_disable,
6188-	.enable		= meson_venc_cvbs_encoder_enable,
6189-	.mode_set	= meson_venc_cvbs_encoder_mode_set,
6190-};
6191-
6192-static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv)
6193-{
6194-	struct device_node *remote;
6195-
6196-	remote = of_graph_get_remote_node(priv->dev->of_node, 0, 0);
6197-	if (!remote)
6198-		return false;
6199-
6200-	of_node_put(remote);
6201-	return true;
6202-}
6203-
6204-int meson_venc_cvbs_create(struct meson_drm *priv)
6205-{
6206-	struct drm_device *drm = priv->drm;
6207-	struct meson_venc_cvbs *meson_venc_cvbs;
6208-	struct drm_connector *connector;
6209-	struct drm_encoder *encoder;
6210-	int ret;
6211-
6212-	if (!meson_venc_cvbs_connector_is_available(priv)) {
6213-		dev_info(drm->dev, "CVBS Output connector not available\n");
6214-		return 0;
6215-	}
6216-
6217-	meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs),
6218-				       GFP_KERNEL);
6219-	if (!meson_venc_cvbs)
6220-		return -ENOMEM;
6221-
6222-	meson_venc_cvbs->priv = priv;
6223-	encoder = &meson_venc_cvbs->encoder;
6224-	connector = &meson_venc_cvbs->connector;
6225-
6226-	/* Connector */
6227-
6228-	drm_connector_helper_add(connector,
6229-				 &meson_cvbs_connector_helper_funcs);
6230-
6231-	ret = drm_connector_init(drm, connector, &meson_cvbs_connector_funcs,
6232-				 DRM_MODE_CONNECTOR_Composite);
6233-	if (ret) {
6234-		dev_err(priv->dev, "Failed to init CVBS connector\n");
6235-		return ret;
6236-	}
6237-
6238-	connector->interlace_allowed = 1;
6239-
6240-	/* Encoder */
6241-
6242-	drm_encoder_helper_add(encoder, &meson_venc_cvbs_encoder_helper_funcs);
6243-
6244-	ret = drm_encoder_init(drm, encoder, &meson_venc_cvbs_encoder_funcs,
6245-			       DRM_MODE_ENCODER_TVDAC, "meson_venc_cvbs");
6246-	if (ret) {
6247-		dev_err(priv->dev, "Failed to init CVBS encoder\n");
6248-		return ret;
6249-	}
6250-
6251-	encoder->possible_crtcs = BIT(0);
6252-
6253-	drm_connector_attach_encoder(connector, encoder);
6254-
6255-	return 0;
6256-}
6257diff -Naur a/drivers/gpu/drm/meson/meson_venc_cvbs.h b/drivers/gpu/drm/meson/meson_venc_cvbs.h
6258--- a/drivers/gpu/drm/meson/meson_venc_cvbs.h	2022-12-19 17:13:12.677518989 +0800
6259+++ b/drivers/gpu/drm/meson/meson_venc_cvbs.h	1970-01-01 08:00:00.000000000 +0800
6260@@ -1,29 +0,0 @@
6261-/* SPDX-License-Identifier: GPL-2.0-or-later */
6262-/*
6263- * Copyright (C) 2016 BayLibre, SAS
6264- * Author: Neil Armstrong <narmstrong@baylibre.com>
6265- * Copyright (C) 2014 Endless Mobile
6266- *
6267- * Written by:
6268- *     Jasper St. Pierre <jstpierre@mecheye.net>
6269- */
6270-
6271-#ifndef __MESON_VENC_CVBS_H
6272-#define __MESON_VENC_CVBS_H
6273-
6274-#include "meson_drv.h"
6275-#include "meson_venc.h"
6276-
6277-struct meson_cvbs_mode {
6278-	struct meson_cvbs_enci_mode *enci;
6279-	struct drm_display_mode mode;
6280-};
6281-
6282-#define MESON_CVBS_MODES_COUNT	2
6283-
6284-/* Modes supported by the CVBS output */
6285-extern struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT];
6286-
6287-int meson_venc_cvbs_create(struct meson_drm *priv);
6288-
6289-#endif /* __MESON_VENC_CVBS_H */
6290diff -Naur a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
6291--- a/drivers/gpu/drm/meson/meson_venc.h	2022-12-19 17:13:12.677518989 +0800
6292+++ b/drivers/gpu/drm/meson/meson_venc.h	2023-02-23 17:02:04.959751069 +0800
6293@@ -21,6 +21,7 @@
6294 	MESON_VENC_MODE_CVBS_PAL,
6295 	MESON_VENC_MODE_CVBS_NTSC,
6296 	MESON_VENC_MODE_HDMI,
6297+	MESON_VENC_MODE_MIPI_DSI,
6298 };
6299
6300 struct meson_cvbs_enci_mode {
6301@@ -47,6 +48,9 @@
6302 	unsigned int analog_sync_adj;
6303 };
6304
6305+/* LCD Encoder gamma setup */
6306+void meson_encl_load_gamma(struct meson_drm *priv);
6307+
6308 /* HDMI Clock parameters */
6309 enum drm_mode_status
6310 meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode);
6311@@ -63,6 +67,8 @@
6312 			      unsigned int ycrcb_map,
6313 			      bool yuv420_mode,
6314 			      const struct drm_display_mode *mode);
6315+void meson_venc_mipi_dsi_mode_set(struct meson_drm *priv,
6316+				  const struct drm_display_mode *mode);
6317 unsigned int meson_venci_get_field(struct meson_drm *priv);
6318
6319 void meson_venc_enable_vsync(struct meson_drm *priv);
6320diff -Naur a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c
6321--- a/drivers/gpu/drm/meson/meson_viu.c	2022-12-19 17:13:12.677518989 +0800
6322+++ b/drivers/gpu/drm/meson/meson_viu.c	2023-02-23 17:02:04.959751069 +0800
6323@@ -78,32 +78,52 @@
6324 	EOTF_COEFF_RIGHTSHIFT /* right shift */
6325 };
6326
6327-static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv,
6328-					   int *m, bool csc_on)
6329+static void meson_viu_set_g12a_osd_matrix(struct meson_drm *priv,
6330+					  int *m, bool csc_on)
6331 {
6332 	/* VPP WRAP OSD1 matrix */
6333 	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
6334 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
6335+	writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
6336+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_PRE_OFFSET0_1));
6337 	writel(m[2] & 0xfff,
6338 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
6339+	writel(m[2] & 0xfff,
6340+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_PRE_OFFSET2));
6341 	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
6342 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
6343+	writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
6344+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_COEF00_01));
6345 	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
6346 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
6347+	writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
6348+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_COEF02_10));
6349 	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
6350 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
6351+	writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
6352+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_COEF11_12));
6353 	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
6354 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
6355-	writel((m[11] & 0x1fff),
6356+	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
6357+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_COEF20_21));
6358+	writel((m[11] & 0x1fff) << 16,
6359 		priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
6360+	writel((m[11] & 0x1fff) << 16,
6361+		priv->io_base +	_REG(VPP_WRAP_OSD2_MATRIX_COEF22));
6362
6363 	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
6364 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
6365+	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
6366+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_OFFSET0_1));
6367 	writel(m[20] & 0xfff,
6368 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
6369+	writel(m[20] & 0xfff,
6370+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_OFFSET2));
6371
6372 	writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
6373 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
6374+	writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
6375+		priv->io_base + _REG(VPP_WRAP_OSD2_MATRIX_EN_CTRL));
6376 }
6377
6378 static void meson_viu_set_osd_matrix(struct meson_drm *priv,
6379@@ -114,21 +134,36 @@
6380 		/* osd matrix, VIU_MATRIX_0 */
6381 		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
6382 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
6383+		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
6384+			priv->io_base + _REG(VIU_OSD2_MATRIX_PRE_OFFSET0_1));
6385 		writel(m[2] & 0xfff,
6386 			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
6387+		writel(m[2] & 0xfff,
6388+			priv->io_base + _REG(VIU_OSD2_MATRIX_PRE_OFFSET2));
6389 		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
6390 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
6391+		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
6392+			priv->io_base + _REG(VIU_OSD2_MATRIX_COEF00_01));
6393 		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
6394 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
6395+		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
6396+			priv->io_base + _REG(VIU_OSD2_MATRIX_COEF02_10));
6397 		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
6398 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
6399+		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
6400+			priv->io_base + _REG(VIU_OSD2_MATRIX_COEF11_12));
6401 		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
6402 			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
6403+		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
6404+			priv->io_base + _REG(VIU_OSD2_MATRIX_COEF20_21));
6405
6406 		if (m[21]) {
6407 			writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
6408 				priv->io_base +
6409 					_REG(VIU_OSD1_MATRIX_COEF22_30));
6410+			writel(((m[11] & 0x1fff) << 16),
6411+				priv->io_base +
6412+					_REG(VIU_OSD2_MATRIX_COEF22));
6413 			writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
6414 				priv->io_base +
6415 					_REG(VIU_OSD1_MATRIX_COEF31_32));
6416@@ -137,14 +172,21 @@
6417 					_REG(VIU_OSD1_MATRIX_COEF40_41));
6418 			writel(m[17] & 0x1fff, priv->io_base +
6419 				_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
6420-		} else
6421+		} else {
6422 			writel((m[11] & 0x1fff) << 16, priv->io_base +
6423 				_REG(VIU_OSD1_MATRIX_COEF22_30));
6424+			writel((m[11] & 0x1fff) << 16, priv->io_base +
6425+				_REG(VIU_OSD2_MATRIX_COEF22));
6426+		}
6427
6428 		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
6429 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
6430+		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
6431+			priv->io_base + _REG(VIU_OSD2_MATRIX_OFFSET0_1));
6432 		writel(m[20] & 0xfff,
6433 			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
6434+		writel(m[20] & 0xfff,
6435+			priv->io_base + _REG(VIU_OSD2_MATRIX_OFFSET2));
6436
6437 		writel_bits_relaxed(3 << 30, m[21] << 30,
6438 			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
6439@@ -154,8 +196,12 @@
6440 		/* 23 reserved for clipping control */
6441 		writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
6442 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
6443+		writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
6444+			priv->io_base + _REG(VIU_OSD2_MATRIX_CTRL));
6445 		writel_bits_relaxed(BIT(1), 0,
6446 			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
6447+		writel_bits_relaxed(BIT(1), 0,
6448+			priv->io_base + _REG(VIU_OSD2_MATRIX_CTRL));
6449 	} else if (m_select == VIU_MATRIX_OSD_EOTF) {
6450 		int i;
6451
6452@@ -426,7 +472,7 @@
6453 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
6454 		meson_viu_load_matrix(priv);
6455 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
6456-		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
6457+		meson_viu_set_g12a_osd_matrix(priv, RGB709_to_YUV709l_coeff,
6458 					       true);
6459 		/* fix green/pink color distortion from vendor u-boot */
6460 		writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
6461@@ -469,14 +515,13 @@
6462 			priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
6463
6464 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
6465-		u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) |
6466-			  (u32)VIU_OSD_BLEND_REORDER(1, 0) |
6467-			  (u32)VIU_OSD_BLEND_REORDER(2, 0) |
6468-			  (u32)VIU_OSD_BLEND_REORDER(3, 0) |
6469-			  (u32)VIU_OSD_BLEND_DIN_EN(1) |
6470-			  (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
6471-			  (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
6472-			  (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
6473+		/* setup bypass to have OSD1->DOUT0 + OSD2->DOUT1 */
6474+		u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) | /* OSD1 to DIN0 */
6475+			  (u32)VIU_OSD_BLEND_REORDER(1, 4) |
6476+			  (u32)VIU_OSD_BLEND_REORDER(2, 4) |
6477+			  (u32)VIU_OSD_BLEND_REORDER(3, 2) | /* OSD2 to DIN3 */
6478+			  (u32)VIU_OSD_BLEND_DIN_EN(9) | /* Enable DIN0 & DIN3 */
6479+			  (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | /* DIN0 to DOUT0 */
6480 			  (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
6481 			  (u32)VIU_OSD_BLEND_HOLD_LINES(4);
6482 		writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
6483diff -Naur a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h
6484--- a/drivers/gpu/drm/meson/meson_vpp.h	2022-12-19 17:13:12.677518989 +0800
6485+++ b/drivers/gpu/drm/meson/meson_vpp.h	2023-02-23 17:02:04.959751069 +0800
6486@@ -12,6 +12,8 @@
6487 struct drm_rect;
6488 struct meson_drm;
6489
6490+/* Mux VIU/VPP to ENCL */
6491+#define MESON_VIU_VPP_MUX_ENCL	0x0
6492 /* Mux VIU/VPP to ENCI */
6493 #define MESON_VIU_VPP_MUX_ENCI	0x5
6494 /* Mux VIU/VPP to ENCP */
6495diff -Naur a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c
6496--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c	2022-12-19 17:13:12.769520092 +0800
6497+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c	2023-02-23 17:02:04.959751069 +0800
6498@@ -81,6 +81,7 @@
6499 }
6500
6501 static struct devfreq_dev_profile panfrost_devfreq_profile = {
6502+	.timer = DEVFREQ_TIMER_DELAYED,
6503 	.polling_ms = 50, /* ~3 frames */
6504 	.target = panfrost_devfreq_target,
6505 	.get_dev_status = panfrost_devfreq_get_dev_status,
6506@@ -134,8 +135,16 @@
6507 	panfrost_devfreq_profile.initial_freq = cur_freq;
6508 	dev_pm_opp_put(opp);
6509
6510+	/*
6511+	* Setup default thresholds for the simple_ondemand governor.
6512+	* The values are chosen based on experiments.
6513+	*/
6514+	pfdevfreq->gov_data.upthreshold = 45;
6515+	pfdevfreq->gov_data.downdifferential = 5;
6516+
6517 	devfreq = devm_devfreq_add_device(dev, &panfrost_devfreq_profile,
6518-					  DEVFREQ_GOV_SIMPLE_ONDEMAND, NULL);
6519+					  DEVFREQ_GOV_SIMPLE_ONDEMAND,
6520+					  &pfdevfreq->gov_data);
6521 	if (IS_ERR(devfreq)) {
6522 		DRM_DEV_ERROR(dev, "Couldn't initialize GPU devfreq\n");
6523 		ret = PTR_ERR(devfreq);
6524diff -Naur a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h
6525--- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h	2022-12-19 17:13:12.769520092 +0800
6526+++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h	2023-02-23 17:02:04.959751069 +0800
6527@@ -4,6 +4,7 @@
6528 #ifndef __PANFROST_DEVFREQ_H__
6529 #define __PANFROST_DEVFREQ_H__
6530
6531+#include <linux/devfreq.h>
6532 #include <linux/spinlock.h>
6533 #include <linux/ktime.h>
6534
6535@@ -17,6 +18,7 @@
6536 	struct devfreq *devfreq;
6537 	struct opp_table *regulators_opp_table;
6538 	struct thermal_cooling_device *cooling;
6539+	struct devfreq_simple_ondemand_data gov_data;
6540 	bool opp_of_table_added;
6541
6542 	ktime_t busy_time;
6543diff -Naur a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
6544--- a/drivers/gpu/drm/panfrost/panfrost_job.c	2022-12-19 17:13:12.769520092 +0800
6545+++ b/drivers/gpu/drm/panfrost/panfrost_job.c	2023-02-23 17:02:04.959751069 +0800
6546@@ -157,7 +157,7 @@
6547
6548 	panfrost_devfreq_record_busy(&pfdev->pfdevfreq);
6549
6550-	ret = pm_runtime_get_sync(pfdev->dev);
6551+	ret = pm_runtime_resume_and_get(pfdev->dev);
6552 	if (ret < 0)
6553 		return;
6554
6555diff -Naur a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
6556--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c	2022-12-19 17:13:12.769520092 +0800
6557+++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c	2023-02-23 17:02:04.959751069 +0800
6558@@ -632,22 +632,20 @@
6559 {
6560 	struct panfrost_device *pfdev = data;
6561 	u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT);
6562-	int i, ret;
6563+	int ret;
6564
6565-	for (i = 0; status; i++) {
6566-		u32 mask = BIT(i) | BIT(i + 16);
6567+	while (status) {
6568+		u32 as = ffs(status | (status >> 16)) - 1;
6569+		u32 mask = BIT(as) | BIT(as + 16);
6570 		u64 addr;
6571 		u32 fault_status;
6572 		u32 exception_type;
6573 		u32 access_type;
6574 		u32 source_id;
6575
6576-		if (!(status & mask))
6577-			continue;
6578-
6579-		fault_status = mmu_read(pfdev, AS_FAULTSTATUS(i));
6580-		addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(i));
6581-		addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(i)) << 32;
6582+		fault_status = mmu_read(pfdev, AS_FAULTSTATUS(as));
6583+		addr = mmu_read(pfdev, AS_FAULTADDRESS_LO(as));
6584+		addr |= (u64)mmu_read(pfdev, AS_FAULTADDRESS_HI(as)) << 32;
6585
6586 		/* decode the fault status */
6587 		exception_type = fault_status & 0xFF;
6588@@ -658,8 +656,8 @@
6589
6590 		/* Page fault only */
6591 		ret = -1;
6592-		if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
6593-			ret = panfrost_mmu_map_fault_addr(pfdev, i, addr);
6594+		if ((status & mask) == BIT(as) && (exception_type & 0xF8) == 0xC0)
6595+			ret = panfrost_mmu_map_fault_addr(pfdev, as, addr);
6596
6597 		if (ret)
6598 			/* terminal fault, print info about the fault */
6599@@ -671,7 +669,7 @@
6600 				"exception type 0x%X: %s\n"
6601 				"access type 0x%X: %s\n"
6602 				"source id 0x%X\n",
6603-				i, addr,
6604+				as, addr,
6605 				"TODO",
6606 				fault_status,
6607 				(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
6608@@ -680,6 +678,10 @@
6609 				source_id);
6610
6611 		status &= ~mask;
6612+
6613+		/* If we received new MMU interrupts, process them before returning. */
6614+		if (!status)
6615+			status = mmu_read(pfdev, MMU_INT_RAWSTAT);
6616 	}
6617
6618 	mmu_write(pfdev, MMU_INT_MASK, ~0);
6619diff -Naur a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
6620--- a/drivers/i2c/muxes/i2c-mux-pca954x.c	2022-12-19 17:13:12.917521866 +0800
6621+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c	2023-02-23 17:02:04.959751069 +0800
6622@@ -401,7 +401,7 @@
6623 	else
6624 		data->last_chan = 0; /* Disconnect multiplexer */
6625
6626-	ret = i2c_smbus_write_byte(client, data->last_chan);
6627+	ret = i2c_smbus_write_byte(client, 15);
6628 	if (ret < 0)
6629 		data->last_chan = 0;
6630
6631diff -Naur a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
6632--- a/drivers/input/touchscreen/edt-ft5x06.c	2022-12-19 17:13:13.073523735 +0800
6633+++ b/drivers/input/touchscreen/edt-ft5x06.c	2023-02-23 17:02:04.959751069 +0800
6634@@ -69,6 +69,11 @@
6635 #define EDT_RAW_DATA_RETRIES		100
6636 #define EDT_RAW_DATA_DELAY		1000 /* usec */
6637
6638+#define EDT_DEFAULT_NUM_X		800
6639+#define EDT_DEFAULT_NUM_Y		480
6640+
6641+#define POLL_INTERVAL_MS		17	/* 17ms = 60fps */
6642+
6643 enum edt_pmode {
6644 	EDT_PMODE_NOT_SUPPORTED,
6645 	EDT_PMODE_HIBERNATE,
6646@@ -121,11 +126,15 @@
6647 	int offset_y;
6648 	int report_rate;
6649 	int max_support_points;
6650+	unsigned int known_ids;
6651
6652 	char name[EDT_NAME_LEN];
6653
6654 	struct edt_reg_addr reg_addr;
6655 	enum edt_ver version;
6656+
6657+	struct timer_list timer;
6658+	struct work_struct work_i2c_poll;
6659 };
6660
6661 struct edt_i2c_chip_data {
6662@@ -192,6 +201,10 @@
6663 	int i, type, x, y, id;
6664 	int offset, tplen, datalen, crclen;
6665 	int error;
6666+	unsigned int active_ids = 0, known_ids = tsdata->known_ids;
6667+	long released_ids;
6668+	int b = 0;
6669+	unsigned int num_points;
6670
6671 	switch (tsdata->version) {
6672 	case EDT_M06:
6673@@ -239,9 +252,15 @@
6674
6675 		if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen))
6676 			goto out;
6677+		num_points = tsdata->max_support_points;
6678+	} else {
6679+		/* Register 2 is TD_STATUS, containing the number of touch
6680+		 * points.
6681+		 */
6682+		num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points);
6683 	}
6684
6685-	for (i = 0; i < tsdata->max_support_points; i++) {
6686+	for (i = 0; i < num_points; i++) {
6687 		u8 *buf = &rdbuf[i * tplen + offset];
6688
6689 		type = buf[0] >> 6;
6690@@ -263,10 +282,25 @@
6691
6692 		input_mt_slot(tsdata->input, id);
6693 		if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER,
6694-					       type != TOUCH_EVENT_UP))
6695+					       type != TOUCH_EVENT_UP)) {
6696 			touchscreen_report_pos(tsdata->input, &tsdata->prop,
6697 					       x, y, true);
6698+			active_ids |= BIT(id);
6699+		} else {
6700+			known_ids &= ~BIT(id);
6701+		}
6702+	}
6703+
6704+	/* One issue with the device is the TOUCH_UP message is not always
6705+	 * returned. Instead track which ids we know about and report when they
6706+	 * are no longer updated
6707+	 */
6708+	released_ids = known_ids & ~active_ids;
6709+	for_each_set_bit_from(b, &released_ids, tsdata->max_support_points) {
6710+		input_mt_slot(tsdata->input, b);
6711+		input_mt_report_slot_inactive(tsdata->input);
6712 	}
6713+	tsdata->known_ids = active_ids;
6714
6715 	input_mt_report_pointer_emulation(tsdata->input, true);
6716 	input_sync(tsdata->input);
6717@@ -275,6 +309,22 @@
6718 	return IRQ_HANDLED;
6719 }
6720
6721+static void edt_ft5x06_ts_irq_poll_timer(struct timer_list *t)
6722+{
6723+	struct edt_ft5x06_ts_data *tsdata = from_timer(tsdata, t, timer);
6724+
6725+	schedule_work(&tsdata->work_i2c_poll);
6726+	mod_timer(&tsdata->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
6727+}
6728+
6729+static void edt_ft5x06_ts_work_i2c_poll(struct work_struct *work)
6730+{
6731+	struct edt_ft5x06_ts_data *tsdata = container_of(work,
6732+			struct edt_ft5x06_ts_data, work_i2c_poll);
6733+
6734+	edt_ft5x06_ts_isr(0, tsdata);
6735+}
6736+
6737 static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
6738 				     u8 addr, u8 value)
6739 {
6740@@ -895,6 +945,7 @@
6741 		 * the identification registers.
6742 		 */
6743 		switch (rdbuf[0]) {
6744+		case 0x11:   /* EDT EP0110M09 */
6745 		case 0x35:   /* EDT EP0350M09 */
6746 		case 0x43:   /* EDT EP0430M09 */
6747 		case 0x50:   /* EDT EP0500M09 */
6748@@ -997,17 +1048,14 @@
6749 	if (reg_addr->reg_report_rate != NO_REGISTER)
6750 		tsdata->report_rate = edt_ft5x06_register_read(tsdata,
6751 						reg_addr->reg_report_rate);
6752-	if (tsdata->version == EDT_M06 ||
6753-	    tsdata->version == EDT_M09 ||
6754-	    tsdata->version == EDT_M12) {
6755+	tsdata->num_x = EDT_DEFAULT_NUM_X;
6756+	if (reg_addr->reg_num_x != NO_REGISTER)
6757 		tsdata->num_x = edt_ft5x06_register_read(tsdata,
6758 							 reg_addr->reg_num_x);
6759+	tsdata->num_y = EDT_DEFAULT_NUM_Y;
6760+	if (reg_addr->reg_num_y != NO_REGISTER)
6761 		tsdata->num_y = edt_ft5x06_register_read(tsdata,
6762 							 reg_addr->reg_num_y);
6763-	} else {
6764-		tsdata->num_x = -1;
6765-		tsdata->num_y = -1;
6766-	}
6767 }
6768
6769 static void
6770@@ -1053,10 +1101,13 @@
6771 	case GENERIC_FT:
6772 		/* this is a guesswork */
6773 		reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
6774+		reg_addr->reg_report_rate = NO_REGISTER;
6775 		reg_addr->reg_gain = M09_REGISTER_GAIN;
6776 		reg_addr->reg_offset = M09_REGISTER_OFFSET;
6777 		reg_addr->reg_offset_x = NO_REGISTER;
6778 		reg_addr->reg_offset_y = NO_REGISTER;
6779+		reg_addr->reg_num_x = NO_REGISTER;
6780+		reg_addr->reg_num_y = NO_REGISTER;
6781 		break;
6782 	}
6783 }
6784@@ -1187,7 +1238,7 @@
6785 	edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
6786 	edt_ft5x06_ts_get_parameters(tsdata);
6787
6788-	dev_dbg(&client->dev,
6789+	dev_info(&client->dev,
6790 		"Model \"%s\", Rev. \"%s\", %dx%d sensors\n",
6791 		tsdata->name, fw_version, tsdata->num_x, tsdata->num_y);
6792
6793@@ -1195,20 +1246,10 @@
6794 	input->id.bustype = BUS_I2C;
6795 	input->dev.parent = &client->dev;
6796
6797-	if (tsdata->version == EDT_M06 ||
6798-	    tsdata->version == EDT_M09 ||
6799-	    tsdata->version == EDT_M12) {
6800-		input_set_abs_params(input, ABS_MT_POSITION_X,
6801-				     0, tsdata->num_x * 64 - 1, 0, 0);
6802-		input_set_abs_params(input, ABS_MT_POSITION_Y,
6803-				     0, tsdata->num_y * 64 - 1, 0, 0);
6804-	} else {
6805-		/* Unknown maximum values. Specify via devicetree */
6806-		input_set_abs_params(input, ABS_MT_POSITION_X,
6807-				     0, 65535, 0, 0);
6808-		input_set_abs_params(input, ABS_MT_POSITION_Y,
6809-				     0, 65535, 0, 0);
6810-	}
6811+	input_set_abs_params(input, ABS_MT_POSITION_X,
6812+			     0, tsdata->num_x * 64 - 1, 0, 0);
6813+	input_set_abs_params(input, ABS_MT_POSITION_Y,
6814+			     0, tsdata->num_y * 64 - 1, 0, 0);
6815
6816 	touchscreen_parse_properties(input, true, &tsdata->prop);
6817
6818@@ -1221,17 +1262,27 @@
6819
6820 	i2c_set_clientdata(client, tsdata);
6821
6822-	irq_flags = irq_get_trigger_type(client->irq);
6823-	if (irq_flags == IRQF_TRIGGER_NONE)
6824-		irq_flags = IRQF_TRIGGER_FALLING;
6825-	irq_flags |= IRQF_ONESHOT;
6826-
6827-	error = devm_request_threaded_irq(&client->dev, client->irq,
6828-					NULL, edt_ft5x06_ts_isr, irq_flags,
6829-					client->name, tsdata);
6830-	if (error) {
6831-		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
6832-		return error;
6833+	if (client->irq) {
6834+		irq_flags = irq_get_trigger_type(client->irq);
6835+		if (irq_flags == IRQF_TRIGGER_NONE)
6836+			irq_flags = IRQF_TRIGGER_FALLING;
6837+		irq_flags |= IRQF_ONESHOT;
6838+
6839+		error = devm_request_threaded_irq(&client->dev, client->irq,
6840+						  NULL, edt_ft5x06_ts_isr,
6841+						  irq_flags, client->name,
6842+						  tsdata);
6843+		if (error) {
6844+			dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
6845+			return error;
6846+		}
6847+	} else {
6848+		INIT_WORK(&tsdata->work_i2c_poll,
6849+			  edt_ft5x06_ts_work_i2c_poll);
6850+		timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0);
6851+		tsdata->timer.expires = jiffies +
6852+					msecs_to_jiffies(POLL_INTERVAL_MS);
6853+		add_timer(&tsdata->timer);
6854 	}
6855
6856 	error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);
6857@@ -1257,6 +1308,10 @@
6858 {
6859 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
6860
6861+	if (!client->irq) {
6862+		del_timer(&tsdata->timer);
6863+		cancel_work_sync(&tsdata->work_i2c_poll);
6864+	}
6865 	edt_ft5x06_ts_teardown_debugfs(tsdata);
6866
6867 	return 0;
6868diff -Naur a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
6869--- a/drivers/irqchip/irq-meson-gpio.c	2022-12-19 17:13:13.097524023 +0800
6870+++ b/drivers/irqchip/irq-meson-gpio.c	2023-02-23 17:02:04.963751125 +0800
6871@@ -15,6 +15,7 @@
6872 #include <linux/irqchip.h>
6873 #include <linux/of.h>
6874 #include <linux/of_address.h>
6875+#include <linux/of_irq.h>
6876
6877 #define NUM_CHANNEL 8
6878 #define MAX_INPUT_MUX 256
6879@@ -136,6 +137,7 @@
6880 struct meson_gpio_irq_controller {
6881 	const struct meson_gpio_irq_params *params;
6882 	void __iomem *base;
6883+	struct irq_domain *domain;
6884 	u32 channel_irqs[NUM_CHANNEL];
6885 	DECLARE_BITMAP(channel_map, NUM_CHANNEL);
6886 	spinlock_t lock;
6887@@ -436,8 +438,8 @@
6888 	.translate	= meson_gpio_irq_domain_translate,
6889 };
6890
6891-static int __init meson_gpio_irq_parse_dt(struct device_node *node,
6892-					  struct meson_gpio_irq_controller *ctl)
6893+static int meson_gpio_irq_parse_dt(struct device_node *node,
6894+				   struct meson_gpio_irq_controller *ctl)
6895 {
6896 	const struct of_device_id *match;
6897 	int ret;
6898@@ -463,63 +465,84 @@
6899 	return 0;
6900 }
6901
6902-static int __init meson_gpio_irq_of_init(struct device_node *node,
6903-					 struct device_node *parent)
6904+static int meson_gpio_intc_probe(struct platform_device *pdev)
6905 {
6906-	struct irq_domain *domain, *parent_domain;
6907+	struct device_node *node = pdev->dev.of_node, *parent;
6908 	struct meson_gpio_irq_controller *ctl;
6909+	struct irq_domain *parent_domain;
6910+	struct resource *res;
6911 	int ret;
6912
6913+	parent = of_irq_find_parent(node);
6914 	if (!parent) {
6915-		pr_err("missing parent interrupt node\n");
6916+		dev_err(&pdev->dev, "missing parent interrupt node\n");
6917 		return -ENODEV;
6918 	}
6919
6920 	parent_domain = irq_find_host(parent);
6921 	if (!parent_domain) {
6922-		pr_err("unable to obtain parent domain\n");
6923+		dev_err(&pdev->dev, "unable to obtain parent domain\n");
6924 		return -ENXIO;
6925 	}
6926
6927-	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
6928+	ctl = devm_kzalloc(&pdev->dev, sizeof(*ctl), GFP_KERNEL);
6929 	if (!ctl)
6930 		return -ENOMEM;
6931
6932 	spin_lock_init(&ctl->lock);
6933
6934-	ctl->base = of_iomap(node, 0);
6935-	if (!ctl->base) {
6936-		ret = -ENOMEM;
6937-		goto free_ctl;
6938-	}
6939+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
6940+	ctl->base = devm_ioremap_resource(&pdev->dev, res);
6941+	if (IS_ERR(ctl->base))
6942+		return PTR_ERR(ctl->base);
6943
6944 	ret = meson_gpio_irq_parse_dt(node, ctl);
6945 	if (ret)
6946-		goto free_channel_irqs;
6947+		return ret;
6948
6949-	domain = irq_domain_create_hierarchy(parent_domain, 0,
6950-					     ctl->params->nr_hwirq,
6951-					     of_node_to_fwnode(node),
6952-					     &meson_gpio_irq_domain_ops,
6953-					     ctl);
6954-	if (!domain) {
6955-		pr_err("failed to add domain\n");
6956-		ret = -ENODEV;
6957-		goto free_channel_irqs;
6958+	ctl->domain = irq_domain_create_hierarchy(parent_domain, 0,
6959+						  ctl->params->nr_hwirq,
6960+						  of_node_to_fwnode(node),
6961+						  &meson_gpio_irq_domain_ops,
6962+						  ctl);
6963+	if (!ctl->domain) {
6964+		dev_err(&pdev->dev, "failed to add domain\n");
6965+		return -ENODEV;
6966 	}
6967
6968-	pr_info("%d to %d gpio interrupt mux initialized\n",
6969-		ctl->params->nr_hwirq, NUM_CHANNEL);
6970+	platform_set_drvdata(pdev, ctl);
6971+
6972+	dev_info(&pdev->dev, "%d to %d gpio interrupt mux initialized\n",
6973+		 ctl->params->nr_hwirq, NUM_CHANNEL);
6974
6975 	return 0;
6976+}
6977
6978-free_channel_irqs:
6979-	iounmap(ctl->base);
6980-free_ctl:
6981-	kfree(ctl);
6982+static int meson_gpio_intc_remove(struct platform_device *pdev)
6983+{
6984+	struct meson_gpio_irq_controller *ctl = platform_get_drvdata(pdev);
6985
6986-	return ret;
6987+	irq_domain_remove(ctl->domain);
6988+
6989+	return 0;
6990 }
6991
6992-IRQCHIP_DECLARE(meson_gpio_intc, "amlogic,meson-gpio-intc",
6993-		meson_gpio_irq_of_init);
6994+static const struct of_device_id meson_gpio_intc_of_match[] = {
6995+	{ .compatible = "amlogic,meson-gpio-intc", },
6996+	{},
6997+};
6998+MODULE_DEVICE_TABLE(of, meson_gpio_intc_of_match);
6999+
7000+static struct platform_driver meson_gpio_intc_driver = {
7001+	.probe  = meson_gpio_intc_probe,
7002+	.remove = meson_gpio_intc_remove,
7003+	.driver = {
7004+		.name = "meson-gpio-intc",
7005+		.of_match_table = meson_gpio_intc_of_match,
7006+	},
7007+};
7008+module_platform_driver(meson_gpio_intc_driver);
7009+
7010+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
7011+MODULE_LICENSE("GPL v2");
7012+MODULE_ALIAS("platform:meson-gpio-intc");
7013diff -Naur a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
7014--- a/drivers/mmc/core/block.c	2022-12-19 17:13:13.441528145 +0800
7015+++ b/drivers/mmc/core/block.c	2023-02-23 17:02:04.963751125 +0800
7016@@ -44,7 +44,9 @@
7017 #include <linux/mmc/host.h>
7018 #include <linux/mmc/mmc.h>
7019 #include <linux/mmc/sd.h>
7020-
7021+#ifdef CONFIG_MMC_MESON_GX
7022+#include <linux/mmc/emmc_partitions.h>
7023+#endif
7024 #include <linux/uaccess.h>
7025
7026 #include "queue.h"
7027@@ -2896,6 +2898,9 @@
7028 {
7029 	struct mmc_blk_data *md, *part_md;
7030 	char cap_str[10];
7031+#ifdef CONFIG_MMC_MESON_GX
7032+	int idx = 0;
7033+#endif
7034
7035 	/*
7036 	 * Check that the card supports the command class(es) we need.
7037@@ -2930,9 +2935,17 @@
7038 	if (mmc_add_disk(md))
7039 		goto out;
7040
7041+#ifdef CONFIG_MMC_MESON_GX
7042+	aml_emmc_partition_ops(card, md->disk);
7043+#endif
7044+
7045 	list_for_each_entry(part_md, &md->part, part) {
7046 		if (mmc_add_disk(part_md))
7047 			goto out;
7048+#ifdef CONFIG_MMC_MESON_GX
7049+		if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT)
7050+			add_fake_boot_partition(part_md->disk, "bootloader%d", idx++);
7051+#endif
7052 	}
7053
7054 	/* Add two debugfs entries */
7055diff -Naur a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
7056--- a/drivers/mmc/host/meson-gx-mmc.c	2022-12-19 17:13:13.449528241 +0800
7057+++ b/drivers/mmc/host/meson-gx-mmc.c	2023-02-23 17:02:04.963751125 +0800
7058@@ -27,6 +27,7 @@
7059 #include <linux/interrupt.h>
7060 #include <linux/bitfield.h>
7061 #include <linux/pinctrl/consumer.h>
7062+#include "../../mmc/core/core.h"
7063
7064 #define DRIVER_NAME "meson-gx-mmc"
7065
7066@@ -38,6 +39,7 @@
7067 #define   CLK_RX_PHASE_MASK GENMASK(13, 12)
7068 #define   CLK_PHASE_0 0
7069 #define   CLK_PHASE_180 2
7070+#define   CLK_PHASE_270 3
7071 #define   CLK_V2_TX_DELAY_MASK GENMASK(19, 16)
7072 #define   CLK_V2_RX_DELAY_MASK GENMASK(23, 20)
7073 #define   CLK_V2_ALWAYS_ON BIT(24)
7074@@ -136,6 +138,7 @@
7075 	unsigned int rx_delay_mask;
7076 	unsigned int always_on;
7077 	unsigned int adjust;
7078+	unsigned int clk_core_phase;
7079 };
7080
7081 struct sd_emmc_desc {
7082@@ -417,7 +420,7 @@
7083 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
7084 	clk_reg = CLK_ALWAYS_ON(host);
7085 	clk_reg |= CLK_DIV_MASK;
7086-	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
7087+	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->data->clk_core_phase);
7088 	clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, CLK_PHASE_0);
7089 	clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, CLK_PHASE_0);
7090 	writel(clk_reg, host->regs + SD_EMMC_CLOCK);
7091@@ -1121,6 +1124,43 @@
7092 	.start_signal_voltage_switch = meson_mmc_voltage_switch,
7093 };
7094
7095+struct mmc_host *sdio_host;
7096+
7097+static void sdio_rescan(struct mmc_host *mmc)
7098+{
7099+	int ret;
7100+
7101+	mmc->rescan_entered = 0;
7102+
7103+	/*mmc->host_rescan_disable = false;*/
7104+	mmc_detect_change(mmc, 0);
7105+
7106+	/* start the delayed_work */
7107+	ret = flush_work(&(mmc->detect.work));
7108+	if (!ret)
7109+		pr_info("Error: sdio_rescan() already idle!\n");
7110+}
7111+
7112+void sdio_reinit(void)
7113+{
7114+	mmc_get_card(sdio_host->card, NULL);
7115+	if (sdio_host) {
7116+		if (sdio_host->card) {
7117+			pr_info("[%s] sdio hw_reset\n", __func__);
7118+			sdio_host->bus_ops->hw_reset(sdio_host);
7119+		}
7120+		else {
7121+			sdio_rescan(sdio_host);
7122+		}
7123+	} else {
7124+		pr_info("Error: sdio_host is NULL\n");
7125+	}
7126+	mmc_put_card(sdio_host->card, NULL);
7127+
7128+	pr_info("[%s] finish\n", __func__);
7129+}
7130+EXPORT_SYMBOL(sdio_reinit);
7131+
7132 static int meson_mmc_probe(struct platform_device *pdev)
7133 {
7134 	struct resource *res;
7135@@ -1279,6 +1319,11 @@
7136 		goto err_bounce_buf;
7137 	}
7138
7139+	/*sdio*/
7140+	if (mmc->pm_caps & MMC_PM_KEEP_POWER) {
7141+		sdio_host = mmc;
7142+	}
7143+
7144 	mmc->ops = &meson_mmc_ops;
7145 	mmc_add_host(mmc);
7146
7147@@ -1328,6 +1373,7 @@
7148 	.rx_delay_mask	= CLK_V2_RX_DELAY_MASK,
7149 	.always_on	= CLK_V2_ALWAYS_ON,
7150 	.adjust		= SD_EMMC_ADJUST,
7151+	.clk_core_phase	= CLK_PHASE_180,
7152 };
7153
7154 static const struct meson_mmc_data meson_axg_data = {
7155@@ -1335,6 +1381,7 @@
7156 	.rx_delay_mask	= CLK_V3_RX_DELAY_MASK,
7157 	.always_on	= CLK_V3_ALWAYS_ON,
7158 	.adjust		= SD_EMMC_V3_ADJUST,
7159+	.clk_core_phase	= CLK_PHASE_270,
7160 };
7161
7162 static const struct of_device_id meson_mmc_of_match[] = {
7163diff -Naur a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
7164--- a/drivers/pinctrl/meson/pinctrl-meson.c	2022-12-19 17:13:14.201537253 +0800
7165+++ b/drivers/pinctrl/meson/pinctrl-meson.c	2023-02-23 17:02:04.963751125 +0800
7166@@ -56,6 +56,24 @@
7167 #include "../pinctrl-utils.h"
7168 #include "pinctrl-meson.h"
7169
7170+static int meson_memory_duplicate(struct platform_device *pdev, void **addr,
7171+				  size_t n, size_t size)
7172+{
7173+	void *mem;
7174+
7175+	if (!(*addr))
7176+		return -EINVAL;
7177+
7178+	mem = devm_kzalloc(&pdev->dev, size * n, GFP_KERNEL);
7179+	if (!mem)
7180+		return -ENOMEM;
7181+
7182+	memcpy(mem, *addr, size * n);
7183+	*addr = mem;
7184+
7185+	return 0;
7186+};
7187+
7188 static const unsigned int meson_bit_strides[] = {
7189 	1, 1, 1, 1, 1, 2, 1
7190 };
7191@@ -152,6 +170,7 @@
7192
7193 	return pc->data->num_funcs;
7194 }
7195+EXPORT_SYMBOL(meson_pmx_get_funcs_count);
7196
7197 const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev,
7198 				    unsigned selector)
7199@@ -160,6 +179,7 @@
7200
7201 	return pc->data->funcs[selector].name;
7202 }
7203+EXPORT_SYMBOL(meson_pmx_get_func_name);
7204
7205 int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector,
7206 			 const char * const **groups,
7207@@ -172,6 +192,7 @@
7208
7209 	return 0;
7210 }
7211+EXPORT_SYMBOL(meson_pmx_get_groups);
7212
7213 static int meson_pinconf_set_gpio_bit(struct meson_pinctrl *pc,
7214 				      unsigned int pin,
7215@@ -248,11 +269,11 @@
7216 {
7217 	int ret;
7218
7219-	ret = meson_pinconf_set_output(pc, pin, true);
7220+	ret = meson_pinconf_set_drive(pc, pin, high);
7221 	if (ret)
7222 		return ret;
7223
7224-	return meson_pinconf_set_drive(pc, pin, high);
7225+	return meson_pinconf_set_output(pc, pin, true);
7226 }
7227
7228 static int meson_pinconf_disable_bias(struct meson_pinctrl *pc,
7229@@ -355,6 +376,7 @@
7230
7231 		switch (param) {
7232 		case PIN_CONFIG_DRIVE_STRENGTH_UA:
7233+		case PIN_CONFIG_INPUT_ENABLE:
7234 		case PIN_CONFIG_OUTPUT_ENABLE:
7235 		case PIN_CONFIG_OUTPUT:
7236 			arg = pinconf_to_config_argument(configs[i]);
7237@@ -383,6 +405,9 @@
7238 		case PIN_CONFIG_OUTPUT:
7239 			ret = meson_pinconf_set_output_drive(pc, pin, arg);
7240 			break;
7241+		case PIN_CONFIG_INPUT_ENABLE:
7242+			ret = meson_pinconf_set_output(pc, pin, !arg);
7243+			break;
7244 		default:
7245 			ret = -ENOTSUPP;
7246 		}
7247@@ -598,9 +623,42 @@
7248 	return !!(val & BIT(bit));
7249 }
7250
7251+static int meson_gpio_to_irq(struct gpio_chip *chip, unsigned int gpio)
7252+{
7253+	struct meson_pinctrl *pc = gpiochip_get_data(chip);
7254+	struct meson_bank *bank;
7255+	struct irq_fwspec fwspec;
7256+	int hwirq;
7257+
7258+	if (meson_get_bank(pc, gpio, &bank))
7259+		return -EINVAL;
7260+
7261+	if (bank->irq_first < 0) {
7262+		dev_warn(pc->dev, "no support irq for pin[%d]\n", gpio);
7263+		return -EINVAL;
7264+	}
7265+
7266+	if (!pc->of_irq) {
7267+		dev_err(pc->dev, "invalid device node of gpio INTC\n");
7268+		return -EINVAL;
7269+	}
7270+
7271+	hwirq = gpio - bank->first + bank->irq_first;
7272+
7273+	fwspec.fwnode = of_node_to_fwnode(pc->of_irq);
7274+	fwspec.param_count = 2;
7275+	fwspec.param[0] = hwirq;
7276+	fwspec.param[1] = IRQ_TYPE_NONE;
7277+
7278+	return irq_create_fwspec_mapping(&fwspec);
7279+}
7280+
7281 static int meson_gpiolib_register(struct meson_pinctrl *pc)
7282 {
7283 	int ret;
7284+	const char **names;
7285+	const struct pinctrl_pin_desc *pins;
7286+	int i;
7287
7288 	pc->chip.label = pc->data->name;
7289 	pc->chip.parent = pc->dev;
7290@@ -612,6 +670,13 @@
7291 	pc->chip.direction_output = meson_gpio_direction_output;
7292 	pc->chip.get = meson_gpio_get;
7293 	pc->chip.set = meson_gpio_set;
7294+	pc->chip.to_irq = meson_gpio_to_irq;
7295+	pc->chip.set_config = gpiochip_generic_config;
7296+	names = kcalloc(pc->desc.npins, sizeof(char *), GFP_KERNEL);
7297+	pins = pc->desc.pins;
7298+	for (i = 0; i < pc->desc.npins; i++)
7299+		names[pins[i].number] = pins[i].name;
7300+	pc->chip.names = (const char * const *)names;
7301 	pc->chip.base = -1;
7302 	pc->chip.ngpio = pc->data->num_pins;
7303 	pc->chip.can_sleep = false;
7304@@ -619,6 +684,16 @@
7305 	pc->chip.of_gpio_n_cells = 2;
7306
7307 	ret = gpiochip_add_data(&pc->chip, pc);
7308+
7309+	/* pin->chip.names will be assigned to each gpio discriptor' name
7310+	 * member after gpiochip_add_data. To keep node name consistency when
7311+	 * use sysfs to export gpio, pc->chip.name need to be cleared also see
7312+	 * gpiod_export->device_create_with_groups.
7313+	 */
7314+	kfree(names);
7315+	names = NULL;
7316+	pc->chip.names = NULL;
7317+
7318 	if (ret) {
7319 		dev_err(pc->dev, "can't add gpio chip %s\n",
7320 			pc->data->name);
7321@@ -681,6 +756,13 @@
7322 	}
7323
7324 	pc->of_node = gpio_np;
7325+	pc->of_irq = of_find_compatible_node(NULL,
7326+					     NULL,
7327+					     "amlogic,meson-gpio-intc-ext");
7328+	if (!pc->of_irq)
7329+		pc->of_irq = of_find_compatible_node(NULL,
7330+						     NULL,
7331+						     "amlogic,meson-gpio-intc");
7332
7333 	pc->reg_mux = meson_map_resource(pc, gpio_np, "mux");
7334 	if (IS_ERR_OR_NULL(pc->reg_mux)) {
7335@@ -750,6 +832,16 @@
7336 	if (ret)
7337 		return ret;
7338
7339+	ret = meson_memory_duplicate(pdev, (void **)&pc->data->groups, pc->data->num_groups,
7340+				     sizeof(struct meson_pmx_group));
7341+	if (ret)
7342+		return ret;
7343+
7344+	ret = meson_memory_duplicate(pdev, (void **)&pc->data->funcs, pc->data->num_funcs,
7345+				     sizeof(struct meson_pmx_func));
7346+	if (ret)
7347+		return ret;
7348+
7349 	pc->desc.name		= "pinctrl-meson";
7350 	pc->desc.owner		= THIS_MODULE;
7351 	pc->desc.pctlops	= &meson_pctrl_ops;
7352@@ -766,3 +858,4 @@
7353
7354 	return meson_gpiolib_register(pc);
7355 }
7356+EXPORT_SYMBOL(meson_pinctrl_probe);
7357diff -Naur a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
7358--- a/drivers/pinctrl/meson/pinctrl-meson.h	2022-12-19 17:13:14.201537253 +0800
7359+++ b/drivers/pinctrl/meson/pinctrl-meson.h	2023-02-23 17:02:04.963751125 +0800
7360@@ -130,6 +130,7 @@
7361 	struct regmap *reg_gpio;
7362 	struct regmap *reg_ds;
7363 	struct gpio_chip chip;
7364+	struct device_node *of_irq;
7365 	struct device_node *of_node;
7366 };
7367
7368diff -Naur a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c
7369--- a/drivers/soc/amlogic/meson-canvas.c	2022-12-19 17:13:14.497540799 +0800
7370+++ b/drivers/soc/amlogic/meson-canvas.c	2023-02-23 17:02:04.963751125 +0800
7371@@ -148,6 +148,24 @@
7372 }
7373 EXPORT_SYMBOL_GPL(meson_canvas_alloc);
7374
7375+int meson_canvas_alloc_spec(struct meson_canvas *canvas, u8 canvas_index)
7376+{
7377+	unsigned long flags;
7378+
7379+	spin_lock_irqsave(&canvas->lock, flags);
7380+	if (!canvas->used[canvas_index]) {
7381+		canvas->used[canvas_index] = 1;
7382+		spin_unlock_irqrestore(&canvas->lock, flags);
7383+		return 0;
7384+	}
7385+	spin_unlock_irqrestore(&canvas->lock, flags);
7386+
7387+	dev_err(canvas->dev, "Canvas (%u) is busy\n", canvas_index);
7388+	return -EBUSY;
7389+}
7390+EXPORT_SYMBOL_GPL(meson_canvas_alloc_spec);
7391+
7392+
7393 int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index)
7394 {
7395 	unsigned long flags;
7396diff -Naur a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
7397--- a/drivers/spi/spi-meson-spicc.c	2023-02-23 10:03:45.602260183 +0800
7398+++ b/drivers/spi/spi-meson-spicc.c	2023-02-23 17:05:24.131300901 +0800
7399@@ -156,7 +156,6 @@
7400 	void __iomem			*base;
7401 	struct clk			*core;
7402 	struct clk			*pclk;
7403-	struct clk_divider		pow2_div;
7404 	struct clk			*clk;
7405 	struct spi_message		*message;
7406 	struct spi_transfer		*xfer;
7407@@ -169,8 +168,6 @@
7408 	unsigned long			xfer_remain;
7409 };
7410
7411-#define pow2_clk_to_spicc(_div) container_of(_div, struct meson_spicc_device, pow2_div)
7412-
7413 static void meson_spicc_oen_enable(struct meson_spicc_device *spicc)
7414 {
7415 	u32 conf;
7416@@ -424,7 +421,7 @@
7417 {
7418 	struct meson_spicc_device *spicc = spi_master_get_devdata(master);
7419 	struct spi_device *spi = message->spi;
7420-	u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK;
7421+	u32 conf = 0;
7422
7423 	/* Store current message */
7424 	spicc->message = message;
7425@@ -461,6 +458,8 @@
7426 	/* Select CS */
7427 	conf |= FIELD_PREP(SPICC_CS_MASK, spi->chip_select);
7428
7429+	/* Default Clock rate core/4 */
7430+
7431 	/* Default 8bit word */
7432 	conf |= FIELD_PREP(SPICC_BITLENGTH_MASK, 8 - 1);
7433
7434@@ -477,16 +476,12 @@
7435 static int meson_spicc_unprepare_transfer(struct spi_master *master)
7436 {
7437 	struct meson_spicc_device *spicc = spi_master_get_devdata(master);
7438-	u32 conf = readl_relaxed(spicc->base + SPICC_CONREG) & SPICC_DATARATE_MASK;
7439
7440 	/* Disable all IRQs */
7441 	writel(0, spicc->base + SPICC_INTREG);
7442
7443 	device_reset_optional(&spicc->pdev->dev);
7444
7445-	/* Set default configuration, keeping datarate field */
7446-	writel_relaxed(conf, spicc->base + SPICC_CONREG);
7447-
7448 	return 0;
7449 }
7450
7451@@ -523,60 +518,14 @@
7452  * Clk path for G12A series:
7453  *    pclk -> pow2 fixed div -> pow2 div -> mux -> out
7454  *    pclk -> enh fixed div -> enh div -> mux -> out
7455- *
7456- * The pow2 divider is tied to the controller HW state, and the
7457- * divider is only valid when the controller is initialized.
7458- *
7459- * A set of clock ops is added to make sure we don't read/set this
7460- * clock rate while the controller is in an unknown state.
7461  */
7462
7463-static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw,
7464-						  unsigned long parent_rate)
7465-{
7466-	struct clk_divider *divider = to_clk_divider(hw);
7467-	struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
7468-
7469-	if (!spicc->master->cur_msg)
7470-		return 0;
7471-
7472-	return clk_divider_ops.recalc_rate(hw, parent_rate);
7473-}
7474-
7475-static int meson_spicc_pow2_determine_rate(struct clk_hw *hw,
7476-					   struct clk_rate_request *req)
7477-{
7478-	struct clk_divider *divider = to_clk_divider(hw);
7479-	struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
7480-
7481-	if (!spicc->master->cur_msg)
7482-		return -EINVAL;
7483-
7484-	return clk_divider_ops.determine_rate(hw, req);
7485-}
7486-
7487-static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate,
7488-				     unsigned long parent_rate)
7489-{
7490-	struct clk_divider *divider = to_clk_divider(hw);
7491-	struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider);
7492-
7493-	if (!spicc->master->cur_msg)
7494-		return -EINVAL;
7495-
7496-	return clk_divider_ops.set_rate(hw, rate, parent_rate);
7497-}
7498-
7499-const struct clk_ops meson_spicc_pow2_clk_ops = {
7500-	.recalc_rate = meson_spicc_pow2_recalc_rate,
7501-	.determine_rate = meson_spicc_pow2_determine_rate,
7502-	.set_rate = meson_spicc_pow2_set_rate,
7503-};
7504-
7505-static int meson_spicc_pow2_clk_init(struct meson_spicc_device *spicc)
7506+static int meson_spicc_clk_init(struct meson_spicc_device *spicc)
7507 {
7508 	struct device *dev = &spicc->pdev->dev;
7509-	struct clk_fixed_factor *pow2_fixed_div;
7510+	struct clk_fixed_factor *pow2_fixed_div, *enh_fixed_div;
7511+	struct clk_divider *pow2_div, *enh_div;
7512+	struct clk_mux *mux;
7513 	struct clk_init_data init;
7514 	struct clk *clk;
7515 	struct clk_parent_data parent_data[2];
7516@@ -611,45 +560,31 @@
7517 	if (WARN_ON(IS_ERR(clk)))
7518 		return PTR_ERR(clk);
7519
7520+	pow2_div = devm_kzalloc(dev, sizeof(*pow2_div), GFP_KERNEL);
7521+	if (!pow2_div)
7522+		return -ENOMEM;
7523+
7524 	snprintf(name, sizeof(name), "%s#pow2_div", dev_name(dev));
7525 	init.name = name;
7526-	init.ops = &meson_spicc_pow2_clk_ops;
7527-	/*
7528-	 * Set NOCACHE here to make sure we read the actual HW value
7529-	 * since we reset the HW after each transfer.
7530-	 */
7531-	init.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
7532+	init.ops = &clk_divider_ops;
7533+	init.flags = CLK_SET_RATE_PARENT;
7534 	parent_data[0].hw = &pow2_fixed_div->hw;
7535 	init.num_parents = 1;
7536
7537-	spicc->pow2_div.shift = 16,
7538-	spicc->pow2_div.width = 3,
7539-	spicc->pow2_div.flags = CLK_DIVIDER_POWER_OF_TWO,
7540-	spicc->pow2_div.reg = spicc->base + SPICC_CONREG;
7541-	spicc->pow2_div.hw.init = &init;
7542-
7543-	spicc->clk = devm_clk_register(dev, &spicc->pow2_div.hw);
7544-	if (WARN_ON(IS_ERR(spicc->clk)))
7545-		return PTR_ERR(spicc->clk);
7546-
7547-	return 0;
7548-}
7549-
7550-static int meson_spicc_enh_clk_init(struct meson_spicc_device *spicc)
7551-{
7552-	struct device *dev = &spicc->pdev->dev;
7553-	struct clk_fixed_factor *enh_fixed_div;
7554-	struct clk_divider *enh_div;
7555-	struct clk_mux *mux;
7556-	struct clk_init_data init;
7557-	struct clk *clk;
7558-	struct clk_parent_data parent_data[2];
7559-	char name[64];
7560+	pow2_div->shift = 16,
7561+	pow2_div->width = 3,
7562+	pow2_div->flags = CLK_DIVIDER_POWER_OF_TWO,
7563+	pow2_div->reg = spicc->base + SPICC_CONREG;
7564+	pow2_div->hw.init = &init;
7565
7566-	memset(&init, 0, sizeof(init));
7567-	memset(&parent_data, 0, sizeof(parent_data));
7568+	clk = devm_clk_register(dev, &pow2_div->hw);
7569+	if (WARN_ON(IS_ERR(clk)))
7570+		return PTR_ERR(clk);
7571
7572-	init.parent_data = parent_data;
7573+	if (!spicc->data->has_enhance_clk_div) {
7574+		spicc->clk = clk;
7575+		return 0;
7576+	}
7577
7578 	/* algorithm for enh div: rate = freq / 2 / (N + 1) */
7579
7580@@ -702,7 +637,7 @@
7581 	snprintf(name, sizeof(name), "%s#sel", dev_name(dev));
7582 	init.name = name;
7583 	init.ops = &clk_mux_ops;
7584-	parent_data[0].hw = &spicc->pow2_div.hw;
7585+	parent_data[0].hw = &pow2_div->hw;
7586 	parent_data[1].hw = &enh_div->hw;
7587 	init.num_parents = 2;
7588 	init.flags = CLK_SET_RATE_PARENT;
7589@@ -758,11 +693,6 @@
7590 	writel_relaxed(0, spicc->base + SPICC_INTREG);
7591
7592 	irq = platform_get_irq(pdev, 0);
7593-	if (irq < 0) {
7594-		ret = irq;
7595-		goto out_master;
7596-	}
7597-
7598 	ret = devm_request_irq(&pdev->dev, irq, meson_spicc_irq,
7599 			       0, NULL, spicc);
7600 	if (ret) {
7601@@ -819,20 +749,12 @@
7602
7603 	meson_spicc_oen_enable(spicc);
7604
7605-	ret = meson_spicc_pow2_clk_init(spicc);
7606+	ret = meson_spicc_clk_init(spicc);
7607 	if (ret) {
7608-		dev_err(&pdev->dev, "pow2 clock registration failed\n");
7609+		dev_err(&pdev->dev, "clock registration failed\n");
7610 		goto out_clk;
7611 	}
7612
7613-	if (spicc->data->has_enhance_clk_div) {
7614-		ret = meson_spicc_enh_clk_init(spicc);
7615-		if (ret) {
7616-			dev_err(&pdev->dev, "clock registration failed\n");
7617-			goto out_clk;
7618-		}
7619-	}
7620-
7621 	ret = devm_spi_register_master(&pdev->dev, master);
7622 	if (ret) {
7623 		dev_err(&pdev->dev, "spi master registration failed\n");
7624diff -Naur a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
7625--- a/drivers/usb/dwc3/dwc3-meson-g12a.c	2022-12-19 17:13:14.765544011 +0800
7626+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c	2023-02-23 17:02:04.963751125 +0800
7627@@ -269,6 +269,59 @@
7628 	const struct dwc3_meson_g12a_drvdata *drvdata;
7629 };
7630
7631+union u2p_r0_v2 {
7632+	/** raw register data */
7633+	uint32_t d32;
7634+	/** register bits */
7635+	struct {
7636+		unsigned host_device:1;
7637+		unsigned power_ok:1;
7638+		unsigned hast_mode:1;
7639+		unsigned power_on_reset:1;
7640+		unsigned id_pullup:1;
7641+		unsigned drv_vbus:1;
7642+		unsigned reserved:26;
7643+	} b;
7644+};
7645+
7646+static ssize_t phy_meson_g12a_usb_mode_show(struct device *dev,
7647+				struct device_attribute *attr,
7648+				char *buf)
7649+{
7650+    struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
7651+    union u2p_r0_v2 reg0;
7652+
7653+    regmap_read(priv->u2p_regmap[1], U2P_R0, &reg0.d32);
7654+    printk(KERN_INFO "USB Mode is %s\n", reg0.b.id_pullup ? "OTG" : "Host");
7655+
7656+	return 0;
7657+}
7658+
7659+static ssize_t phy_meson_g12a_usb_mode_store(struct device *dev,
7660+				struct device_attribute *attr,
7661+				const char *buf, size_t count)
7662+{
7663+    struct dwc3_meson_g12a *priv = dev_get_drvdata(dev);
7664+	int id_pullup = 0;
7665+
7666+    id_pullup = simple_strtoul(buf, NULL, 16);
7667+    printk(KERN_INFO "USB Mode : %s\n", id_pullup ? "OTG" : "Host");
7668+
7669+    if (id_pullup) {
7670+        regmap_update_bits(priv->u2p_regmap[1], U2P_R0,
7671+                    U2P_R0_HOST_DEVICE | U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
7672+                    U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
7673+    } else {
7674+        regmap_update_bits(priv->u2p_regmap[1], U2P_R0,
7675+                    U2P_R0_HOST_DEVICE | U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
7676+                    U2P_R0_HOST_DEVICE | U2P_R0_DRV_VBUS);
7677+    }
7678+
7679+	return count;
7680+}
7681+
7682+static DEVICE_ATTR(usb_mode, 0664, phy_meson_g12a_usb_mode_show, phy_meson_g12a_usb_mode_store);
7683+
7684 static int dwc3_meson_gxl_set_phy_mode(struct dwc3_meson_g12a *priv,
7685 					 int i, enum phy_mode mode)
7686 {
7687@@ -436,6 +489,10 @@
7688
7689 	dwc3_meson_g12a_usb_otg_apply_mode(priv, mode);
7690
7691+    ret = device_create_file(priv->dev, &dev_attr_usb_mode);
7692+    if (ret != 0)
7693+        dev_err(priv->dev, "failed create usb mode file\n");
7694+
7695 	return 0;
7696 }
7697
7698diff -Naur a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
7699--- a/drivers/usb/gadget/composite.c	2022-12-19 17:13:14.769544059 +0800
7700+++ b/drivers/usb/gadget/composite.c	2023-02-23 17:02:04.963751125 +0800
7701@@ -2061,7 +2061,7 @@
7702 	return value;
7703 }
7704
7705-void composite_disconnect(struct usb_gadget *gadget)
7706+static void __composite_disconnect(struct usb_gadget *gadget)
7707 {
7708 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
7709 	unsigned long			flags;
7710@@ -2078,6 +2078,23 @@
7711 	spin_unlock_irqrestore(&cdev->lock, flags);
7712 }
7713
7714+void composite_disconnect(struct usb_gadget *gadget)
7715+{
7716+	usb_gadget_vbus_draw(gadget, 0);
7717+	__composite_disconnect(gadget);
7718+}
7719+
7720+void composite_reset(struct usb_gadget *gadget)
7721+{
7722+	/*
7723+	 * Section 1.4.13 Standard Downstream Port of the USB battery charging
7724+	 * specification v1.2 states that a device connected on a SDP shall only
7725+	 * draw at max 100mA while in a connected, but unconfigured state.
7726+	 */
7727+	usb_gadget_vbus_draw(gadget, 100);
7728+	__composite_disconnect(gadget);
7729+}
7730+
7731 /*-------------------------------------------------------------------------*/
7732
7733 static ssize_t suspended_show(struct device *dev, struct device_attribute *attr,
7734@@ -2398,7 +2415,7 @@
7735 	.unbind		= composite_unbind,
7736
7737 	.setup		= composite_setup,
7738-	.reset		= composite_disconnect,
7739+	.reset		= composite_reset,
7740 	.disconnect	= composite_disconnect,
7741
7742 	.suspend	= composite_suspend,
7743diff -Naur a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
7744--- a/drivers/usb/gadget/configfs.c	2022-12-19 17:13:14.769544059 +0800
7745+++ b/drivers/usb/gadget/configfs.c	2023-02-23 17:02:04.963751125 +0800
7746@@ -10,6 +10,32 @@
7747 #include "u_f.h"
7748 #include "u_os_desc.h"
7749
7750+#ifdef CONFIG_USB_CONFIGFS_UEVENT
7751+#include <linux/platform_device.h>
7752+#include <linux/kdev_t.h>
7753+#include <linux/usb/ch9.h>
7754+
7755+#ifdef CONFIG_USB_CONFIGFS_F_ACC
7756+extern int acc_ctrlrequest(struct usb_composite_dev *cdev,
7757+				const struct usb_ctrlrequest *ctrl);
7758+void acc_disconnect(void);
7759+#endif
7760+static struct class *android_class;
7761+static struct device *android_device;
7762+static int index;
7763+static int gadget_index;
7764+
7765+struct device *create_function_device(char *name)
7766+{
7767+	if (android_device && !IS_ERR(android_device))
7768+		return device_create(android_class, android_device,
7769+			MKDEV(0, index++), NULL, name);
7770+	else
7771+		return ERR_PTR(-EINVAL);
7772+}
7773+EXPORT_SYMBOL_GPL(create_function_device);
7774+#endif
7775+
7776 int check_user_usb_string(const char *name,
7777 		struct usb_gadget_strings *stringtab_dev)
7778 {
7779@@ -51,6 +77,12 @@
7780 	char qw_sign[OS_STRING_QW_SIGN_LEN];
7781 	spinlock_t spinlock;
7782 	bool unbind;
7783+#ifdef CONFIG_USB_CONFIGFS_UEVENT
7784+	bool connected;
7785+	bool sw_connected;
7786+	struct work_struct work;
7787+	struct device *dev;
7788+#endif
7789 };
7790
7791 static inline struct gadget_info *to_gadget_info(struct config_item *item)
7792@@ -272,7 +304,7 @@
7793
7794 	mutex_lock(&gi->lock);
7795
7796-	if (!strlen(name)) {
7797+	if (!strlen(name) || strcmp(name, "none") == 0) {
7798 		ret = unregister_gadget(gi);
7799 		if (ret)
7800 			goto err;
7801@@ -1270,6 +1302,9 @@
7802 					f->name, f);
7803 				f->unbind(c, f);
7804 			}
7805+
7806+			if (f->bind_deactivated)
7807+				usb_function_activate(f);
7808 		}
7809 		c->next_interface_id = 0;
7810 		memset(c->interface, 0, sizeof(c->interface));
7811@@ -1422,6 +1457,57 @@
7812 	return ret;
7813 }
7814
7815+#ifdef CONFIG_USB_CONFIGFS_UEVENT
7816+static void android_work(struct work_struct *data)
7817+{
7818+	struct gadget_info *gi = container_of(data, struct gadget_info, work);
7819+	struct usb_composite_dev *cdev = &gi->cdev;
7820+	char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
7821+	char *connected[2]    = { "USB_STATE=CONNECTED", NULL };
7822+	char *configured[2]   = { "USB_STATE=CONFIGURED", NULL };
7823+	/* 0-connected 1-configured 2-disconnected*/
7824+	bool status[3] = { false, false, false };
7825+	unsigned long flags;
7826+	bool uevent_sent = false;
7827+
7828+	spin_lock_irqsave(&cdev->lock, flags);
7829+	if (cdev->config)
7830+		status[1] = true;
7831+
7832+	if (gi->connected != gi->sw_connected) {
7833+		if (gi->connected)
7834+			status[0] = true;
7835+		else
7836+			status[2] = true;
7837+		gi->sw_connected = gi->connected;
7838+	}
7839+	spin_unlock_irqrestore(&cdev->lock, flags);
7840+
7841+	if (status[0]) {
7842+		kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, connected);
7843+		pr_info("%s: sent uevent %s\n", __func__, connected[0]);
7844+		uevent_sent = true;
7845+	}
7846+
7847+	if (status[1]) {
7848+		kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, configured);
7849+		pr_info("%s: sent uevent %s\n", __func__, configured[0]);
7850+		uevent_sent = true;
7851+	}
7852+
7853+	if (status[2]) {
7854+		kobject_uevent_env(&gi->dev->kobj, KOBJ_CHANGE, disconnected);
7855+		pr_info("%s: sent uevent %s\n", __func__, disconnected[0]);
7856+		uevent_sent = true;
7857+	}
7858+
7859+	if (!uevent_sent) {
7860+		pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
7861+			gi->connected, gi->sw_connected, cdev->config);
7862+	}
7863+}
7864+#endif
7865+
7866 static void configfs_composite_unbind(struct usb_gadget *gadget)
7867 {
7868 	struct usb_composite_dev	*cdev;
7869@@ -1449,6 +1535,51 @@
7870 	spin_unlock_irqrestore(&gi->spinlock, flags);
7871 }
7872
7873+#ifdef CONFIG_USB_CONFIGFS_UEVENT
7874+static int android_setup(struct usb_gadget *gadget,
7875+			const struct usb_ctrlrequest *c)
7876+{
7877+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
7878+	unsigned long flags;
7879+	struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
7880+	int value = -EOPNOTSUPP;
7881+	struct usb_function_instance *fi;
7882+
7883+	spin_lock_irqsave(&cdev->lock, flags);
7884+	if (c->bRequest == USB_REQ_GET_DESCRIPTOR &&
7885+	    (c->wValue >> 8) == USB_DT_CONFIG && !gi->connected) {
7886+		gi->connected = 1;
7887+		schedule_work(&gi->work);
7888+	}
7889+	spin_unlock_irqrestore(&cdev->lock, flags);
7890+	list_for_each_entry(fi, &gi->available_func, cfs_list) {
7891+		if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) {
7892+			value = fi->f->setup(fi->f, c);
7893+			if (value >= 0)
7894+				break;
7895+		}
7896+	}
7897+
7898+#ifdef CONFIG_USB_CONFIGFS_F_ACC
7899+	if (value < 0)
7900+		value = acc_ctrlrequest(cdev, c);
7901+#endif
7902+
7903+	if (value < 0)
7904+		value = composite_setup(gadget, c);
7905+
7906+	spin_lock_irqsave(&cdev->lock, flags);
7907+	if (c->bRequest == USB_REQ_SET_CONFIGURATION &&
7908+						cdev->config) {
7909+		schedule_work(&gi->work);
7910+	}
7911+	spin_unlock_irqrestore(&cdev->lock, flags);
7912+
7913+	return value;
7914+}
7915+
7916+#else // CONFIG_USB_CONFIGFS_UEVENT
7917+
7918 static int configfs_composite_setup(struct usb_gadget *gadget,
7919 		const struct usb_ctrlrequest *ctrl)
7920 {
7921@@ -1474,6 +1605,8 @@
7922 	return ret;
7923 }
7924
7925+#endif // CONFIG_USB_CONFIGFS_UEVENT
7926+
7927 static void configfs_composite_disconnect(struct usb_gadget *gadget)
7928 {
7929 	struct usb_composite_dev *cdev;
7930@@ -1484,6 +1617,14 @@
7931 	if (!cdev)
7932 		return;
7933
7934+#ifdef CONFIG_USB_CONFIGFS_F_ACC
7935+	/*
7936+	 * accessory HID support can be active while the
7937+	 * accessory function is not actually enabled,
7938+	 * so we need to inform it when we are disconnected.
7939+	 */
7940+	acc_disconnect();
7941+#endif
7942 	gi = container_of(cdev, struct gadget_info, cdev);
7943 	spin_lock_irqsave(&gi->spinlock, flags);
7944 	cdev = get_gadget_data(gadget);
7945@@ -1492,10 +1633,36 @@
7946 		return;
7947 	}
7948
7949+#ifdef CONFIG_USB_CONFIGFS_UEVENT
7950+	gi->connected = 0;
7951+	schedule_work(&gi->work);
7952+#endif
7953 	composite_disconnect(gadget);
7954 	spin_unlock_irqrestore(&gi->spinlock, flags);
7955 }
7956
7957+static void configfs_composite_reset(struct usb_gadget *gadget)
7958+{
7959+	struct usb_composite_dev *cdev;
7960+	struct gadget_info *gi;
7961+	unsigned long flags;
7962+
7963+	cdev = get_gadget_data(gadget);
7964+	if (!cdev)
7965+		return;
7966+
7967+	gi = container_of(cdev, struct gadget_info, cdev);
7968+	spin_lock_irqsave(&gi->spinlock, flags);
7969+	cdev = get_gadget_data(gadget);
7970+	if (!cdev || gi->unbind) {
7971+		spin_unlock_irqrestore(&gi->spinlock, flags);
7972+		return;
7973+	}
7974+
7975+	composite_reset(gadget);
7976+	spin_unlock_irqrestore(&gi->spinlock, flags);
7977+}
7978+
7979 static void configfs_composite_suspend(struct usb_gadget *gadget)
7980 {
7981 	struct usb_composite_dev *cdev;
7982@@ -1544,10 +1711,13 @@
7983 	.bind           = configfs_composite_bind,
7984 	.unbind         = configfs_composite_unbind,
7985
7986+#ifdef CONFIG_USB_CONFIGFS_UEVENT
7987+	.setup          = android_setup,
7988+#else
7989 	.setup          = configfs_composite_setup,
7990-	.reset          = configfs_composite_disconnect,
7991+#endif
7992+	.reset          = configfs_composite_reset,
7993 	.disconnect     = configfs_composite_disconnect,
7994-
7995 	.suspend	= configfs_composite_suspend,
7996 	.resume		= configfs_composite_resume,
7997
7998@@ -1559,6 +1729,91 @@
7999 	.match_existing_only = 1,
8000 };
8001
8002+#ifdef CONFIG_USB_CONFIGFS_UEVENT
8003+static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
8004+			char *buf)
8005+{
8006+	struct gadget_info *dev = dev_get_drvdata(pdev);
8007+	struct usb_composite_dev *cdev;
8008+	char *state = "DISCONNECTED";
8009+	unsigned long flags;
8010+
8011+	if (!dev)
8012+		goto out;
8013+
8014+	cdev = &dev->cdev;
8015+
8016+	if (!cdev)
8017+		goto out;
8018+
8019+	spin_lock_irqsave(&cdev->lock, flags);
8020+	if (cdev->config)
8021+		state = "CONFIGURED";
8022+	else if (dev->connected)
8023+		state = "CONNECTED";
8024+	spin_unlock_irqrestore(&cdev->lock, flags);
8025+out:
8026+	return sprintf(buf, "%s\n", state);
8027+}
8028+
8029+static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
8030+
8031+static struct device_attribute *android_usb_attributes[] = {
8032+	&dev_attr_state,
8033+	NULL
8034+};
8035+
8036+static int android_device_create(struct gadget_info *gi)
8037+{
8038+	struct device_attribute **attrs;
8039+	struct device_attribute *attr;
8040+
8041+	INIT_WORK(&gi->work, android_work);
8042+	gi->dev = device_create(android_class, NULL,
8043+			MKDEV(0, 0), NULL, "android%d", gadget_index++);
8044+	if (IS_ERR(gi->dev))
8045+		return PTR_ERR(gi->dev);
8046+
8047+	dev_set_drvdata(gi->dev, gi);
8048+	if (!android_device)
8049+		android_device = gi->dev;
8050+
8051+	attrs = android_usb_attributes;
8052+	while ((attr = *attrs++)) {
8053+		int err;
8054+
8055+		err = device_create_file(gi->dev, attr);
8056+		if (err) {
8057+			device_destroy(gi->dev->class,
8058+				       gi->dev->devt);
8059+			return err;
8060+		}
8061+	}
8062+
8063+	return 0;
8064+}
8065+
8066+static void android_device_destroy(struct gadget_info *gi)
8067+{
8068+	struct device_attribute **attrs;
8069+	struct device_attribute *attr;
8070+
8071+	attrs = android_usb_attributes;
8072+	while ((attr = *attrs++))
8073+		device_remove_file(gi->dev, attr);
8074+	device_destroy(gi->dev->class, gi->dev->devt);
8075+}
8076+#else
8077+static inline int android_device_create(struct gadget_info *gi)
8078+{
8079+	return 0;
8080+}
8081+
8082+static inline void android_device_destroy(struct gadget_info *gi)
8083+{
8084+}
8085+#endif
8086+
8087 static struct config_group *gadgets_make(
8088 		struct config_group *group,
8089 		const char *name)
8090@@ -1611,7 +1866,11 @@
8091 	if (!gi->composite.gadget_driver.function)
8092 		goto err;
8093
8094+	if (android_device_create(gi) < 0)
8095+		goto err;
8096+
8097 	return &gi->group;
8098+
8099 err:
8100 	kfree(gi);
8101 	return ERR_PTR(-ENOMEM);
8102@@ -1619,7 +1878,11 @@
8103
8104 static void gadgets_drop(struct config_group *group, struct config_item *item)
8105 {
8106+	struct gadget_info *gi;
8107+
8108+	gi = container_of(to_config_group(item), struct gadget_info, group);
8109 	config_item_put(item);
8110+	android_device_destroy(gi);
8111 }
8112
8113 static struct configfs_group_operations gadgets_ops = {
8114@@ -1659,6 +1922,13 @@
8115 	config_group_init(&gadget_subsys.su_group);
8116
8117 	ret = configfs_register_subsystem(&gadget_subsys);
8118+
8119+#ifdef CONFIG_USB_CONFIGFS_UEVENT
8120+	android_class = class_create(THIS_MODULE, "android_usb");
8121+	if (IS_ERR(android_class))
8122+		return PTR_ERR(android_class);
8123+#endif
8124+
8125 	return ret;
8126 }
8127 module_init(gadget_cfs_init);
8128@@ -1666,5 +1936,10 @@
8129 static void __exit gadget_cfs_exit(void)
8130 {
8131 	configfs_unregister_subsystem(&gadget_subsys);
8132+#ifdef CONFIG_USB_CONFIGFS_UEVENT
8133+	if (!IS_ERR(android_class))
8134+		class_destroy(android_class);
8135+#endif
8136+
8137 }
8138 module_exit(gadget_cfs_exit);
8139diff -Naur a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
8140--- a/drivers/usb/gadget/Kconfig	2022-12-19 17:13:14.769544059 +0800
8141+++ b/drivers/usb/gadget/Kconfig	2023-02-23 17:02:04.963751125 +0800
8142@@ -216,6 +216,12 @@
8143 config USB_F_TCM
8144 	tristate
8145
8146+config USB_F_ACC
8147+	tristate
8148+
8149+config USB_F_AUDIO_SRC
8150+	tristate
8151+
8152 # this first set of drivers all depend on bulk-capable hardware.
8153
8154 config USB_CONFIGFS
8155@@ -230,6 +236,14 @@
8156 	  appropriate symbolic links.
8157 	  For more information see Documentation/usb/gadget_configfs.rst.
8158
8159+config USB_CONFIGFS_UEVENT
8160+	bool "Uevent notification of Gadget state"
8161+	depends on USB_CONFIGFS
8162+	help
8163+	  Enable uevent notifications to userspace when the gadget
8164+	  state changes. The gadget can be in any of the following
8165+	  three states: "CONNECTED/DISCONNECTED/CONFIGURED"
8166+
8167 config USB_CONFIGFS_SERIAL
8168 	bool "Generic serial bulk in/out"
8169 	depends on USB_CONFIGFS
8170@@ -371,6 +385,23 @@
8171 	  implemented in kernel space (for instance Ethernet, serial or
8172 	  mass storage) and other are implemented in user space.
8173
8174+config USB_CONFIGFS_F_ACC
8175+	bool "Accessory gadget"
8176+	depends on USB_CONFIGFS
8177+	depends on HID=y
8178+	select USB_F_ACC
8179+	help
8180+	  USB gadget Accessory support
8181+
8182+config USB_CONFIGFS_F_AUDIO_SRC
8183+	bool "Audio Source gadget"
8184+	depends on USB_CONFIGFS
8185+	depends on SND
8186+	select SND_PCM
8187+	select USB_F_AUDIO_SRC
8188+	help
8189+	  USB gadget Audio Source support
8190+
8191 config USB_CONFIGFS_F_UAC1
8192 	bool "Audio Class 1.0"
8193 	depends on USB_CONFIGFS
8194diff -Naur a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
8195--- a/drivers/usb/serial/ch341.c	2022-12-19 17:13:14.821544682 +0800
8196+++ b/drivers/usb/serial/ch341.c	2023-02-23 17:02:04.963751125 +0800
8197@@ -84,6 +84,7 @@
8198 	{ USB_DEVICE(0x1a86, 0x5523) },
8199 	{ USB_DEVICE(0x1a86, 0x7522) },
8200 	{ USB_DEVICE(0x1a86, 0x7523) },
8201+	{ USB_DEVICE(0x1a86, 0xe019) },
8202 	{ USB_DEVICE(0x2184, 0x0057) },
8203 	{ USB_DEVICE(0x4348, 0x5523) },
8204 	{ USB_DEVICE(0x9986, 0x7523) },
8205diff -Naur a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
8206--- a/drivers/video/fbdev/core/fbcon.c	2022-12-19 17:13:14.865545209 +0800
8207+++ b/drivers/video/fbdev/core/fbcon.c	2023-02-23 17:02:04.967751180 +0800
8208@@ -365,6 +365,7 @@
8209
8210 static void fb_flashcursor(struct work_struct *work)
8211 {
8212+#ifdef CONSOLE_CURSOR_ON
8213 	struct fb_info *info = container_of(work, struct fb_info, queue);
8214 	struct fbcon_ops *ops = info->fbcon_par;
8215 	struct vc_data *vc = NULL;
8216@@ -395,6 +396,7 @@
8217 	ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
8218 		    get_color(vc, info, c, 0));
8219 	console_unlock();
8220+#endif
8221 }
8222
8223 static void cursor_timer_handler(struct timer_list *t)
8224@@ -1331,6 +1333,7 @@
8225
8226 static void fbcon_cursor(struct vc_data *vc, int mode)
8227 {
8228+#ifdef CONSOLE_CURSOR_ON
8229 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
8230 	struct fbcon_ops *ops = info->fbcon_par;
8231  	int c = scr_readw((u16 *) vc->vc_pos);
8232@@ -1352,6 +1355,7 @@
8233
8234 	ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
8235 		    get_color(vc, info, c, 0));
8236+#endif
8237 }
8238
8239 static int scrollback_phys_max = 0;
8240diff -Naur a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
8241--- a/drivers/video/fbdev/core/fbmem.c	2022-12-19 17:13:14.865545209 +0800
8242+++ b/drivers/video/fbdev/core/fbmem.c	2023-02-23 17:02:04.967751180 +0800
8243@@ -53,9 +53,9 @@
8244 int num_registered_fb __read_mostly;
8245 EXPORT_SYMBOL(num_registered_fb);
8246
8247-bool fb_center_logo __read_mostly;
8248+bool fb_center_logo = true;
8249
8250-int fb_logo_count __read_mostly = -1;
8251+int fb_logo_count = 1;
8252
8253 static struct fb_info *get_fb_info(unsigned int idx)
8254 {
8255diff -Naur a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
8256--- a/include/drm/bridge/dw_hdmi.h	2022-12-19 17:13:15.185549044 +0800
8257+++ b/include/drm/bridge/dw_hdmi.h	2023-02-23 17:02:04.967751180 +0800
8258@@ -126,6 +126,8 @@
8259 struct dw_hdmi_plat_data {
8260 	struct regmap *regm;
8261
8262+	unsigned int output_port;
8263+
8264 	unsigned long input_bus_encoding;
8265 	bool use_drm_infoframe;
8266 	bool ycbcr_420_allowed;
8267@@ -153,6 +155,8 @@
8268 	const struct dw_hdmi_phy_config *phy_config;
8269 	int (*configure_phy)(struct dw_hdmi *hdmi, void *data,
8270 			     unsigned long mpixelclock);
8271+
8272+	unsigned int disable_cec : 1;
8273 };
8274
8275 struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
8276diff -Naur a/include/drm/bridge/dw_mipi_dsi.h b/include/drm/bridge/dw_mipi_dsi.h
8277--- a/include/drm/bridge/dw_mipi_dsi.h	2022-12-19 17:13:15.185549044 +0800
8278+++ b/include/drm/bridge/dw_mipi_dsi.h	2023-02-23 17:02:04.967751180 +0800
8279@@ -51,7 +51,9 @@
8280 	unsigned int max_data_lanes;
8281
8282 	enum drm_mode_status (*mode_valid)(void *priv_data,
8283-					   const struct drm_display_mode *mode);
8284+					   const struct drm_display_mode *mode,
8285+					   unsigned long mode_flags,
8286+					   u32 lanes, u32 format);
8287
8288 	const struct dw_mipi_dsi_phy_ops *phy_ops;
8289 	const struct dw_mipi_dsi_host_ops *host_ops;
8290diff -Naur a/include/drm/drm_aperture.h b/include/drm/drm_aperture.h
8291--- a/include/drm/drm_aperture.h	1970-01-01 08:00:00.000000000 +0800
8292+++ b/include/drm/drm_aperture.h	2023-02-23 17:02:04.967751180 +0800
8293@@ -0,0 +1,39 @@
8294+/* SPDX-License-Identifier: MIT */
8295+
8296+#ifndef _DRM_APERTURE_H_
8297+#define _DRM_APERTURE_H_
8298+
8299+#include <linux/types.h>
8300+
8301+struct drm_device;
8302+struct drm_driver;
8303+struct pci_dev;
8304+
8305+int devm_aperture_acquire_from_firmware(struct drm_device *dev, resource_size_t base,
8306+					resource_size_t size);
8307+
8308+int drm_aperture_remove_conflicting_framebuffers(resource_size_t base, resource_size_t size,
8309+						 bool primary, const struct drm_driver *req_driver);
8310+
8311+int drm_aperture_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
8312+						     const struct drm_driver *req_driver);
8313+
8314+/**
8315+ * drm_aperture_remove_framebuffers - remove all existing framebuffers
8316+ * @primary: also kick vga16fb if present
8317+ * @req_driver: requesting DRM driver
8318+ *
8319+ * This function removes all graphics device drivers. Use this function on systems
8320+ * that can have their framebuffer located anywhere in memory.
8321+ *
8322+ * Returns:
8323+ * 0 on success, or a negative errno code otherwise
8324+ */
8325+static inline int
8326+drm_aperture_remove_framebuffers(bool primary, const struct drm_driver *req_driver)
8327+{
8328+	return drm_aperture_remove_conflicting_framebuffers(0, (resource_size_t)-1, primary,
8329+							    req_driver);
8330+}
8331+
8332+#endif
8333diff -Naur a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
8334--- a/include/drm/drm_atomic_helper.h	2022-12-19 17:13:15.185549044 +0800
8335+++ b/include/drm/drm_atomic_helper.h	2023-02-23 17:02:04.967751180 +0800
8336@@ -167,7 +167,7 @@
8337 	drm_for_each_plane_mask(plane, (crtc)->dev, (crtc)->state->plane_mask)
8338
8339 /**
8340- * drm_crtc_atomic_state_for_each_plane - iterate over attached planes in new state
8341+ * drm_atomic_crtc_state_for_each_plane - iterate over attached planes in new state
8342  * @plane: the loop cursor
8343  * @crtc_state: the incoming CRTC state
8344  *
8345@@ -180,7 +180,7 @@
8346 	drm_for_each_plane_mask(plane, (crtc_state)->state->dev, (crtc_state)->plane_mask)
8347
8348 /**
8349- * drm_crtc_atomic_state_for_each_plane_state - iterate over attached planes in new state
8350+ * drm_atomic_crtc_state_for_each_plane_state - iterate over attached planes in new state
8351  * @plane: the loop cursor
8352  * @plane_state: loop cursor for the plane's state, must be const
8353  * @crtc_state: the incoming CRTC state
8354diff -Naur a/include/drm/drm_connector.h b/include/drm/drm_connector.h
8355--- a/include/drm/drm_connector.h	2022-12-19 17:13:15.185549044 +0800
8356+++ b/include/drm/drm_connector.h	2023-02-23 17:02:04.967751180 +0800
8357@@ -1622,6 +1622,9 @@
8358 					       u32 scaling_mode_mask);
8359 int drm_connector_attach_vrr_capable_property(
8360 		struct drm_connector *connector);
8361+int drm_connector_attach_hdr_output_metadata_property(struct drm_connector *connector);
8362+bool drm_connector_atomic_hdr_metadata_equal(struct drm_connector_state *old_state,
8363+					     struct drm_connector_state *new_state);
8364 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
8365 int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector);
8366 int drm_mode_create_dp_colorspace_property(struct drm_connector *connector);
8367diff -Naur a/include/dt-bindings/clock/g12a-clkc.h b/include/dt-bindings/clock/g12a-clkc.h
8368--- a/include/dt-bindings/clock/g12a-clkc.h	2022-12-19 17:13:15.193549139 +0800
8369+++ b/include/dt-bindings/clock/g12a-clkc.h	2023-02-23 17:02:04.967751180 +0800
8370@@ -147,5 +147,26 @@
8371 #define CLKID_SPICC1_SCLK			261
8372 #define CLKID_NNA_AXI_CLK			264
8373 #define CLKID_NNA_CORE_CLK			267
8374+#define CLKID_MIPI_DSI_PXCLK_SEL		269
8375+#define CLKID_MIPI_DSI_PXCLK			270
8376+#define CLKID_24M						271
8377+#define CLKID_MIPI_ISP_CLK_COMP			272
8378+#define CLKID_MIPI_CSI_PHY_CLK0_COMP	273
8379
8380+#define CLKID_VDEC_P0_COMP				274
8381+#define CLKID_VDEC_P1_COMP				275
8382+#define CLKID_VDEC_MUX					276
8383+#define CLKID_HCODEC_P0_COMP			277
8384+#define CLKID_HCODEC_P1_COMP			278
8385+#define CLKID_HCODEC_MUX				279
8386+#define CLKID_HEVC_P0_COMP				280
8387+#define CLKID_HEVC_P1_COMP				281
8388+#define CLKID_HEVC_MUX					282
8389+#define CLKID_HEVCF_P0_COMP				283
8390+#define CLKID_HEVCF_P1_COMP				284
8391+#define CLKID_HEVCF_MUX					285
8392+
8393+#define CLKID_VPU_CLKB_TMP_COMP			286
8394+#define CLKID_VPU_CLKB_COMP				287
8395+
8396 #endif /* __G12A_CLKC_H */
8397diff -Naur a/include/linux/mmc/card.h b/include/linux/mmc/card.h
8398--- a/include/linux/mmc/card.h	2022-12-19 17:13:15.285550241 +0800
8399+++ b/include/linux/mmc/card.h	2023-02-23 17:02:04.967751180 +0800
8400@@ -310,6 +310,7 @@
8401 	struct dentry		*debugfs_root;
8402 	struct mmc_part	part[MMC_NUM_PHY_PARTITION]; /* physical partitions */
8403 	unsigned int    nr_parts;
8404+	unsigned int    key_stamp;
8405
8406 	unsigned int		bouncesz;	/* Bounce buffer size */
8407 	struct workqueue_struct *complete_wq;	/* Private workqueue */
8408diff -Naur a/include/linux/mmc/emmc_partitions.h b/include/linux/mmc/emmc_partitions.h
8409--- a/include/linux/mmc/emmc_partitions.h	1970-01-01 08:00:00.000000000 +0800
8410+++ b/include/linux/mmc/emmc_partitions.h	2023-02-23 17:02:04.967751180 +0800
8411@@ -0,0 +1,85 @@
8412+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
8413+/*
8414+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
8415+ */
8416+
8417+#ifndef _EMMC_PARTITIONS_H
8418+#define _EMMC_PARTITIONS_H
8419+
8420+#include<linux/genhd.h>
8421+
8422+#include <linux/mmc/host.h>
8423+#include <linux/mmc/card.h>
8424+#include <linux/mmc/mmc.h>
8425+#include <linux/mmc/core.h>
8426+
8427+/* #include <mach/register.h> */
8428+/* #include <mach/am_regs.h> */
8429+#define CONFIG_DTB_SIZE  (256 * 1024U)
8430+#define DTB_CELL_SIZE	(16 * 1024U)
8431+#define	STORE_CODE				1
8432+#define	STORE_CACHE				BIT(1)
8433+#define	STORE_DATA				BIT(2)
8434+
8435+#define     MAX_PART_NAME_LEN               16
8436+#define     MAX_MMC_PART_NUM                32
8437+
8438+/* MMC Partition Table */
8439+#define     MMC_PARTITIONS_MAGIC            "MPT"
8440+#define     MMC_RESERVED_NAME               "reserved"
8441+
8442+#define     SZ_1M                           0x00100000
8443+
8444+/* the size of bootloader partition */
8445+#define     MMC_BOOT_PARTITION_SIZE         (4 * SZ_1M)
8446+#define		MMC_TUNING_OFFSET               0X14400
8447+
8448+/* the size of reserve space behind bootloader partition */
8449+#define     MMC_BOOT_PARTITION_RESERVED     (32 * SZ_1M)
8450+
8451+#define     RESULT_OK                       0
8452+#define     RESULT_FAIL                     1
8453+#define     RESULT_UNSUP_HOST               2
8454+#define     RESULT_UNSUP_CARD               3
8455+
8456+struct partitions {
8457+	/* identifier string */
8458+	char name[MAX_PART_NAME_LEN];
8459+	/* partition size, byte unit */
8460+	u64 size;
8461+	/* offset within the master space, byte unit */
8462+	u64 offset;
8463+	/* master flags to mask out for this partition */
8464+	unsigned int mask_flags;
8465+};
8466+
8467+struct mmc_partitions_fmt {
8468+	char magic[4];
8469+	unsigned char version[12];
8470+	int part_num;
8471+	int checksum;
8472+	struct partitions partitions[MAX_MMC_PART_NUM];
8473+};
8474+
8475+/*#ifdef CONFIG_MMC_AML*/
8476+int aml_emmc_partition_ops(struct mmc_card *card, struct gendisk *disk);
8477+int add_fake_boot_partition(struct gendisk *disk, char *name, int idx);
8478+/*
8479+ *#else
8480+ *static inline int aml_emmc_partition_ops(struct mmc_card *card,
8481+ *					 struct gendisk *disk)
8482+ *{
8483+ *	return -1;
8484+ *}
8485+ *#endif
8486+ */
8487+unsigned int mmc_capacity(struct mmc_card *card);
8488+int mmc_read_internal(struct mmc_card *card,
8489+		      unsigned int dev_addr, unsigned int blocks, void *buf);
8490+int mmc_write_internal(struct mmc_card *card,
8491+		       unsigned int dev_addr, unsigned int blocks, void *buf);
8492+int get_reserve_partition_off_from_tbl(void);
8493+#endif
8494+
8495+extern struct mmc_partitions_fmt *pt_fmt;
8496+
8497diff -Naur a/include/linux/soc/amlogic/meson-canvas.h b/include/linux/soc/amlogic/meson-canvas.h
8498--- a/include/linux/soc/amlogic/meson-canvas.h	2022-12-19 17:13:15.329550769 +0800
8499+++ b/include/linux/soc/amlogic/meson-canvas.h	2023-02-23 17:02:04.967751180 +0800
8500@@ -39,6 +39,14 @@
8501 int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index);
8502
8503 /**
8504+ * meson_canvas_alloc_spec() - take ownership of a canvas
8505+ *
8506+ * @canvas: canvas provider instance retrieved from meson_canvas_get()
8507+ * @canvas_index: the specified canvas index
8508+ */
8509+int meson_canvas_alloc_spec(struct meson_canvas *canvas, u8 canvas_index);
8510+
8511+/**
8512  * meson_canvas_free() - remove ownership from a canvas
8513  *
8514  * @canvas: canvas provider instance retrieved from meson_canvas_get()
8515diff -Naur a/include/linux/usb/composite.h b/include/linux/usb/composite.h
8516--- a/include/linux/usb/composite.h	2022-12-19 17:13:15.345550961 +0800
8517+++ b/include/linux/usb/composite.h	2023-02-23 17:02:04.967751180 +0800
8518@@ -525,6 +525,8 @@
8519 extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
8520
8521 extern void composite_disconnect(struct usb_gadget *gadget);
8522+extern void composite_reset(struct usb_gadget *gadget);
8523+
8524 extern int composite_setup(struct usb_gadget *gadget,
8525 		const struct usb_ctrlrequest *ctrl);
8526 extern void composite_suspend(struct usb_gadget *gadget);
8527@@ -590,6 +592,7 @@
8528 	struct config_group group;
8529 	struct list_head cfs_list;
8530 	struct usb_function_driver *fd;
8531+	struct usb_function *f;
8532 	int (*set_inst_name)(struct usb_function_instance *inst,
8533 			      const char *name);
8534 	void (*free_func_inst)(struct usb_function_instance *inst);
8535diff -Naur a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
8536--- a/kernel/dma/contiguous.c	2022-12-19 17:13:15.481552591 +0800
8537+++ b/kernel/dma/contiguous.c	2023-02-23 17:02:04.967751180 +0800
8538@@ -262,6 +262,7 @@
8539
8540 	return cma_alloc(dev_get_cma_area(dev), count, align, no_warn);
8541 }
8542+EXPORT_SYMBOL(dma_alloc_from_contiguous);
8543
8544 /**
8545  * dma_release_from_contiguous() - release allocated pages
8546@@ -278,6 +279,7 @@
8547 {
8548 	return cma_release(dev_get_cma_area(dev), pages, count);
8549 }
8550+EXPORT_SYMBOL(dma_release_from_contiguous);
8551
8552 static struct page *cma_alloc_aligned(struct cma *cma, size_t size, gfp_t gfp)
8553 {
8554diff -Naur a/kernel/sched/core.c b/kernel/sched/core.c
8555--- a/kernel/sched/core.c	2022-12-19 17:13:15.505552878 +0800
8556+++ b/kernel/sched/core.c	2023-02-23 17:02:04.967751180 +0800
8557@@ -5711,6 +5711,7 @@
8558 {
8559 	return _sched_setscheduler(p, policy, param, true);
8560 }
8561+EXPORT_SYMBOL_GPL(sched_setscheduler);
8562
8563 int sched_setattr(struct task_struct *p, const struct sched_attr *attr)
8564 {
8565diff -Naur a/Makefile b/Makefile
8566--- a/Makefile	2023-02-08 19:27:44.107724365 +0800
8567+++ b/Makefile	2023-02-23 17:02:04.971751235 +0800
8568@@ -491,6 +491,7 @@
8569 		-I$(objtree)/arch/$(SRCARCH)/include/generated \
8570 		$(if $(building_out_of_srctree),-I$(srctree)/include) \
8571 		-I$(objtree)/include \
8572+		-I$(objtree)/vendor/include \
8573 		$(USERINCLUDE)
8574
8575 KBUILD_AFLAGS   := -D__ASSEMBLY__ -fno-PIE
8576@@ -861,7 +862,7 @@
8577 endif
8578
8579 endif # CONFIG_DEBUG_INFO
8580-
8581+KBUILD_CFLAGS += -Wno-unused-function
8582 KBUILD_CFLAGS += $(DEBUG_CFLAGS)
8583 export DEBUG_CFLAGS
8584
8585@@ -987,7 +988,7 @@
8586 KBUILD_CFLAGS   += -Werror=date-time
8587
8588 # enforce correct pointer usage
8589-KBUILD_CFLAGS   += $(call cc-option,-Werror=incompatible-pointer-types)
8590+#KBUILD_CFLAGS   += $(call cc-option,-Werror=incompatible-pointer-types)
8591
8592 # Require designated initializers for all marked structures
8593 KBUILD_CFLAGS   += $(call cc-option,-Werror=designated-init)
8594@@ -1391,7 +1392,7 @@
8595 # Devicetree files
8596
8597 ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/boot/dts/),)
8598-dtstree := arch/$(SRCARCH)/boot/dts
8599+dtstree := vendor/arch/$(SRCARCH)/boot/dts
8600 endif
8601
8602 ifneq ($(dtstree),)
8603