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, ®0.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