.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2016 BayLibre, SAS |
---|
3 | 4 | * Author: Neil Armstrong <narmstrong@baylibre.com> |
---|
4 | 5 | * Copyright (C) 2015 Amlogic, Inc. All rights reserved. |
---|
5 | 6 | * Copyright (C) 2014 Endless Mobile |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License as |
---|
9 | | - * published by the Free Software Foundation; either version 2 of the |
---|
10 | | - * License, or (at your option) any later version. |
---|
11 | | - * |
---|
12 | | - * This program is distributed in the hope that it will be useful, but |
---|
13 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
15 | | - * General Public License for more details. |
---|
16 | | - * |
---|
17 | | - * You should have received a copy of the GNU General Public License |
---|
18 | | - * along with this program; if not, see <http://www.gnu.org/licenses/>. |
---|
19 | 7 | */ |
---|
20 | 8 | |
---|
21 | | -#include <linux/kernel.h> |
---|
22 | | -#include <linux/module.h> |
---|
23 | | -#include <drm/drmP.h> |
---|
| 9 | +#include <linux/export.h> |
---|
| 10 | +#include <linux/bitfield.h> |
---|
| 11 | + |
---|
| 12 | +#include <drm/drm_fourcc.h> |
---|
| 13 | + |
---|
24 | 14 | #include "meson_drv.h" |
---|
25 | 15 | #include "meson_viu.h" |
---|
26 | | -#include "meson_vpp.h" |
---|
27 | | -#include "meson_venc.h" |
---|
28 | | -#include "meson_canvas.h" |
---|
29 | 16 | #include "meson_registers.h" |
---|
30 | 17 | |
---|
31 | 18 | /** |
---|
.. | .. |
---|
91 | 78 | EOTF_COEFF_RIGHTSHIFT /* right shift */ |
---|
92 | 79 | }; |
---|
93 | 80 | |
---|
94 | | -void meson_viu_set_osd_matrix(struct meson_drm *priv, |
---|
95 | | - enum viu_matrix_sel_e m_select, |
---|
| 81 | +static void meson_viu_set_g12a_osd1_matrix(struct meson_drm *priv, |
---|
| 82 | + int *m, bool csc_on) |
---|
| 83 | +{ |
---|
| 84 | + /* VPP WRAP OSD1 matrix */ |
---|
| 85 | + writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff), |
---|
| 86 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1)); |
---|
| 87 | + writel(m[2] & 0xfff, |
---|
| 88 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2)); |
---|
| 89 | + writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff), |
---|
| 90 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01)); |
---|
| 91 | + writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff), |
---|
| 92 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10)); |
---|
| 93 | + writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff), |
---|
| 94 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12)); |
---|
| 95 | + writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff), |
---|
| 96 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21)); |
---|
| 97 | + writel((m[11] & 0x1fff), |
---|
| 98 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22)); |
---|
| 99 | + |
---|
| 100 | + writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff), |
---|
| 101 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1)); |
---|
| 102 | + writel(m[20] & 0xfff, |
---|
| 103 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2)); |
---|
| 104 | + |
---|
| 105 | + writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0, |
---|
| 106 | + priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL)); |
---|
| 107 | +} |
---|
| 108 | + |
---|
| 109 | +static void meson_viu_set_osd_matrix(struct meson_drm *priv, |
---|
| 110 | + enum viu_matrix_sel_e m_select, |
---|
96 | 111 | int *m, bool csc_on) |
---|
97 | 112 | { |
---|
98 | 113 | if (m_select == VIU_MATRIX_OSD) { |
---|
.. | .. |
---|
160 | 175 | #define OSD_EOTF_LUT_SIZE 33 |
---|
161 | 176 | #define OSD_OETF_LUT_SIZE 41 |
---|
162 | 177 | |
---|
163 | | -void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, |
---|
164 | | - unsigned int *r_map, unsigned int *g_map, |
---|
165 | | - unsigned int *b_map, |
---|
166 | | - bool csc_on) |
---|
| 178 | +static void |
---|
| 179 | +meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel, |
---|
| 180 | + unsigned int *r_map, unsigned int *g_map, |
---|
| 181 | + unsigned int *b_map, bool csc_on) |
---|
167 | 182 | { |
---|
168 | 183 | unsigned int addr_port; |
---|
169 | 184 | unsigned int data_port; |
---|
.. | .. |
---|
296 | 311 | true); |
---|
297 | 312 | } |
---|
298 | 313 | |
---|
| 314 | +/* VIU OSD1 Reset as workaround for GXL+ Alpha OSD Bug */ |
---|
| 315 | +void meson_viu_osd1_reset(struct meson_drm *priv) |
---|
| 316 | +{ |
---|
| 317 | + uint32_t osd1_fifo_ctrl_stat, osd1_ctrl_stat2; |
---|
| 318 | + |
---|
| 319 | + /* Save these 2 registers state */ |
---|
| 320 | + osd1_fifo_ctrl_stat = readl_relaxed( |
---|
| 321 | + priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); |
---|
| 322 | + osd1_ctrl_stat2 = readl_relaxed( |
---|
| 323 | + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); |
---|
| 324 | + |
---|
| 325 | + /* Reset OSD1 */ |
---|
| 326 | + writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1, |
---|
| 327 | + priv->io_base + _REG(VIU_SW_RESET)); |
---|
| 328 | + writel_bits_relaxed(VIU_SW_RESET_OSD1, 0, |
---|
| 329 | + priv->io_base + _REG(VIU_SW_RESET)); |
---|
| 330 | + |
---|
| 331 | + /* Rewrite these registers state lost in the reset */ |
---|
| 332 | + writel_relaxed(osd1_fifo_ctrl_stat, |
---|
| 333 | + priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); |
---|
| 334 | + writel_relaxed(osd1_ctrl_stat2, |
---|
| 335 | + priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); |
---|
| 336 | + |
---|
| 337 | + /* Reload the conversion matrix */ |
---|
| 338 | + meson_viu_load_matrix(priv); |
---|
| 339 | +} |
---|
| 340 | + |
---|
| 341 | +#define OSD1_MALI_ORDER_ABGR \ |
---|
| 342 | + (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \ |
---|
| 343 | + VIU_OSD1_MALI_REORDER_A) | \ |
---|
| 344 | + FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \ |
---|
| 345 | + VIU_OSD1_MALI_REORDER_B) | \ |
---|
| 346 | + FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \ |
---|
| 347 | + VIU_OSD1_MALI_REORDER_G) | \ |
---|
| 348 | + FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \ |
---|
| 349 | + VIU_OSD1_MALI_REORDER_R)) |
---|
| 350 | + |
---|
| 351 | +#define OSD1_MALI_ORDER_ARGB \ |
---|
| 352 | + (FIELD_PREP(VIU_OSD1_MALI_AFBCD_A_REORDER, \ |
---|
| 353 | + VIU_OSD1_MALI_REORDER_A) | \ |
---|
| 354 | + FIELD_PREP(VIU_OSD1_MALI_AFBCD_B_REORDER, \ |
---|
| 355 | + VIU_OSD1_MALI_REORDER_R) | \ |
---|
| 356 | + FIELD_PREP(VIU_OSD1_MALI_AFBCD_G_REORDER, \ |
---|
| 357 | + VIU_OSD1_MALI_REORDER_G) | \ |
---|
| 358 | + FIELD_PREP(VIU_OSD1_MALI_AFBCD_R_REORDER, \ |
---|
| 359 | + VIU_OSD1_MALI_REORDER_B)) |
---|
| 360 | + |
---|
| 361 | +void meson_viu_g12a_enable_osd1_afbc(struct meson_drm *priv) |
---|
| 362 | +{ |
---|
| 363 | + u32 afbc_order = OSD1_MALI_ORDER_ARGB; |
---|
| 364 | + |
---|
| 365 | + /* Enable Mali AFBC Unpack */ |
---|
| 366 | + writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, |
---|
| 367 | + VIU_OSD1_MALI_UNPACK_EN, |
---|
| 368 | + priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL)); |
---|
| 369 | + |
---|
| 370 | + switch (priv->afbcd.format) { |
---|
| 371 | + case DRM_FORMAT_XBGR8888: |
---|
| 372 | + case DRM_FORMAT_ABGR8888: |
---|
| 373 | + afbc_order = OSD1_MALI_ORDER_ABGR; |
---|
| 374 | + break; |
---|
| 375 | + } |
---|
| 376 | + |
---|
| 377 | + /* Setup RGBA Reordering */ |
---|
| 378 | + writel_bits_relaxed(VIU_OSD1_MALI_AFBCD_A_REORDER | |
---|
| 379 | + VIU_OSD1_MALI_AFBCD_B_REORDER | |
---|
| 380 | + VIU_OSD1_MALI_AFBCD_G_REORDER | |
---|
| 381 | + VIU_OSD1_MALI_AFBCD_R_REORDER, |
---|
| 382 | + afbc_order, |
---|
| 383 | + priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL)); |
---|
| 384 | + |
---|
| 385 | + /* Select AFBCD path for OSD1 */ |
---|
| 386 | + writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, |
---|
| 387 | + OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, |
---|
| 388 | + priv->io_base + _REG(OSD_PATH_MISC_CTRL)); |
---|
| 389 | +} |
---|
| 390 | + |
---|
| 391 | +void meson_viu_g12a_disable_osd1_afbc(struct meson_drm *priv) |
---|
| 392 | +{ |
---|
| 393 | + /* Disable AFBCD path for OSD1 */ |
---|
| 394 | + writel_bits_relaxed(OSD_PATH_OSD_AXI_SEL_OSD1_AFBCD, 0, |
---|
| 395 | + priv->io_base + _REG(OSD_PATH_MISC_CTRL)); |
---|
| 396 | + |
---|
| 397 | + /* Disable AFBCD unpack */ |
---|
| 398 | + writel_bits_relaxed(VIU_OSD1_MALI_UNPACK_EN, 0, |
---|
| 399 | + priv->io_base + _REG(VIU_OSD1_MALI_UNPACK_CTRL)); |
---|
| 400 | +} |
---|
| 401 | + |
---|
| 402 | +void meson_viu_gxm_enable_osd1_afbc(struct meson_drm *priv) |
---|
| 403 | +{ |
---|
| 404 | + writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x90), |
---|
| 405 | + priv->io_base + _REG(VIU_MISC_CTRL1)); |
---|
| 406 | +} |
---|
| 407 | + |
---|
| 408 | +void meson_viu_gxm_disable_osd1_afbc(struct meson_drm *priv) |
---|
| 409 | +{ |
---|
| 410 | + writel_bits_relaxed(MALI_AFBC_MISC, FIELD_PREP(MALI_AFBC_MISC, 0x00), |
---|
| 411 | + priv->io_base + _REG(VIU_MISC_CTRL1)); |
---|
| 412 | +} |
---|
| 413 | + |
---|
299 | 414 | void meson_viu_init(struct meson_drm *priv) |
---|
300 | 415 | { |
---|
301 | 416 | uint32_t reg; |
---|
302 | 417 | |
---|
303 | 418 | /* Disable OSDs */ |
---|
304 | | - writel_bits_relaxed(BIT(0) | BIT(21), 0, |
---|
305 | | - priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); |
---|
306 | | - writel_bits_relaxed(BIT(0) | BIT(21), 0, |
---|
307 | | - priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); |
---|
| 419 | + writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, |
---|
| 420 | + priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); |
---|
| 421 | + writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, |
---|
| 422 | + priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); |
---|
308 | 423 | |
---|
309 | 424 | /* On GXL/GXM, Use the 10bit HDR conversion matrix */ |
---|
310 | | - if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || |
---|
311 | | - meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) |
---|
| 425 | + if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) || |
---|
| 426 | + meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) |
---|
312 | 427 | meson_viu_load_matrix(priv); |
---|
| 428 | + else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { |
---|
| 429 | + meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff, |
---|
| 430 | + true); |
---|
| 431 | + /* fix green/pink color distortion from vendor u-boot */ |
---|
| 432 | + writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT | |
---|
| 433 | + OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0, |
---|
| 434 | + priv->io_base + _REG(OSD1_HDR2_CTRL)); |
---|
| 435 | + } |
---|
313 | 436 | |
---|
314 | 437 | /* Initialize OSD1 fifo control register */ |
---|
315 | | - reg = BIT(0) | /* Urgent DDR request priority */ |
---|
316 | | - (4 << 5) | /* hold_fifo_lines */ |
---|
317 | | - (3 << 10) | /* burst length 64 */ |
---|
318 | | - (32 << 12) | /* fifo_depth_val: 32*8=256 */ |
---|
319 | | - (2 << 22) | /* 4 words in 1 burst */ |
---|
320 | | - (2 << 24); |
---|
| 438 | + reg = VIU_OSD_DDR_PRIORITY_URGENT | |
---|
| 439 | + VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ |
---|
| 440 | + VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ |
---|
| 441 | + VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ |
---|
| 442 | + |
---|
| 443 | + if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) |
---|
| 444 | + reg |= (VIU_OSD_BURST_LENGTH_32 | VIU_OSD_HOLD_FIFO_LINES(31)); |
---|
| 445 | + else |
---|
| 446 | + reg |= (VIU_OSD_BURST_LENGTH_64 | VIU_OSD_HOLD_FIFO_LINES(4)); |
---|
| 447 | + |
---|
321 | 448 | writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); |
---|
322 | 449 | writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); |
---|
323 | 450 | |
---|
.. | .. |
---|
329 | 456 | 0xff << OSD_REPLACE_SHIFT, |
---|
330 | 457 | priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); |
---|
331 | 458 | |
---|
| 459 | + /* Disable VD1 AFBC */ |
---|
| 460 | + /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/ |
---|
| 461 | + writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0, |
---|
| 462 | + priv->io_base + _REG(VIU_MISC_CTRL0)); |
---|
| 463 | + writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE)); |
---|
| 464 | + |
---|
| 465 | + writel_relaxed(0x00FF00C0, |
---|
| 466 | + priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE)); |
---|
| 467 | + writel_relaxed(0x00FF00C0, |
---|
| 468 | + priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); |
---|
| 469 | + |
---|
| 470 | + if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { |
---|
| 471 | + u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) | |
---|
| 472 | + (u32)VIU_OSD_BLEND_REORDER(1, 0) | |
---|
| 473 | + (u32)VIU_OSD_BLEND_REORDER(2, 0) | |
---|
| 474 | + (u32)VIU_OSD_BLEND_REORDER(3, 0) | |
---|
| 475 | + (u32)VIU_OSD_BLEND_DIN_EN(1) | |
---|
| 476 | + (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | |
---|
| 477 | + (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | |
---|
| 478 | + (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | |
---|
| 479 | + (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | |
---|
| 480 | + (u32)VIU_OSD_BLEND_HOLD_LINES(4); |
---|
| 481 | + writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); |
---|
| 482 | + |
---|
| 483 | + writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, |
---|
| 484 | + priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); |
---|
| 485 | + writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, |
---|
| 486 | + priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); |
---|
| 487 | + writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); |
---|
| 488 | + writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL)); |
---|
| 489 | + writel_relaxed(0, |
---|
| 490 | + priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0)); |
---|
| 491 | + writel_relaxed(0, |
---|
| 492 | + priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA)); |
---|
| 493 | + |
---|
| 494 | + writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), |
---|
| 495 | + priv->io_base + _REG(DOLBY_PATH_CTRL)); |
---|
| 496 | + |
---|
| 497 | + meson_viu_g12a_disable_osd1_afbc(priv); |
---|
| 498 | + } |
---|
| 499 | + |
---|
| 500 | + if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) |
---|
| 501 | + meson_viu_gxm_disable_osd1_afbc(priv); |
---|
| 502 | + |
---|
332 | 503 | priv->viu.osd1_enabled = false; |
---|
333 | 504 | priv->viu.osd1_commit = false; |
---|
334 | 505 | priv->viu.osd1_interlace = false; |
---|