meson_vpu_init.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Amlogic Meson Video Processing Unit driver
  4. *
  5. * Copyright (c) 2018 BayLibre, SAS.
  6. * Author: Neil Armstrong <narmstrong@baylibre.com>
  7. */
  8. #define DEBUG
  9. #include <common.h>
  10. #include <dm.h>
  11. #include <asm/io.h>
  12. #include <linux/bitops.h>
  13. #include "meson_vpu.h"
  14. /* HHI Registers */
  15. #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
  16. #define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */
  17. #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
  18. #define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */
  19. #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */
  20. /* OSDx_CTRL_STAT2 */
  21. #define OSD_REPLACE_EN BIT(14)
  22. #define OSD_REPLACE_SHIFT 6
  23. void meson_vpp_setup_mux(struct meson_vpu_priv *priv, unsigned int mux)
  24. {
  25. writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
  26. }
  27. static unsigned int vpp_filter_coefs_4point_bspline[] = {
  28. 0x15561500, 0x14561600, 0x13561700, 0x12561800,
  29. 0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
  30. 0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
  31. 0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
  32. 0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
  33. 0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
  34. 0x05473301, 0x05463401, 0x04453601, 0x04433702,
  35. 0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
  36. 0x033d3d03
  37. };
  38. static void meson_vpp_write_scaling_filter_coefs(struct meson_vpu_priv *priv,
  39. const unsigned int *coefs,
  40. bool is_horizontal)
  41. {
  42. int i;
  43. writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
  44. priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
  45. for (i = 0; i < 33; i++)
  46. writel(coefs[i],
  47. priv->io_base + _REG(VPP_OSD_SCALE_COEF));
  48. }
  49. static const u32 vpp_filter_coefs_bicubic[] = {
  50. 0x00800000, 0x007f0100, 0xff7f0200, 0xfe7f0300,
  51. 0xfd7e0500, 0xfc7e0600, 0xfb7d0800, 0xfb7c0900,
  52. 0xfa7b0b00, 0xfa7a0dff, 0xf9790fff, 0xf97711ff,
  53. 0xf87613ff, 0xf87416fe, 0xf87218fe, 0xf8701afe,
  54. 0xf76f1dfd, 0xf76d1ffd, 0xf76b21fd, 0xf76824fd,
  55. 0xf76627fc, 0xf76429fc, 0xf7612cfc, 0xf75f2ffb,
  56. 0xf75d31fb, 0xf75a34fb, 0xf75837fa, 0xf7553afa,
  57. 0xf8523cfa, 0xf8503ff9, 0xf84d42f9, 0xf84a45f9,
  58. 0xf84848f8
  59. };
  60. static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_vpu_priv *priv,
  61. const unsigned int *coefs,
  62. bool is_horizontal)
  63. {
  64. int i;
  65. writel(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0,
  66. priv->io_base + _REG(VPP_SCALE_COEF_IDX));
  67. for (i = 0; i < 33; i++)
  68. writel(coefs[i],
  69. priv->io_base + _REG(VPP_SCALE_COEF));
  70. }
  71. /* OSD csc defines */
  72. enum viu_matrix_sel_e {
  73. VIU_MATRIX_OSD_EOTF = 0,
  74. VIU_MATRIX_OSD,
  75. };
  76. enum viu_lut_sel_e {
  77. VIU_LUT_OSD_EOTF = 0,
  78. VIU_LUT_OSD_OETF,
  79. };
  80. #define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
  81. #define MATRIX_5X3_COEF_SIZE 24
  82. #define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
  83. #define EOTF_COEFF_SIZE 10
  84. #define EOTF_COEFF_RIGHTSHIFT 1
  85. static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
  86. 0, 0, 0, /* pre offset */
  87. COEFF_NORM(0.181873), COEFF_NORM(0.611831), COEFF_NORM(0.061765),
  88. COEFF_NORM(-0.100251), COEFF_NORM(-0.337249), COEFF_NORM(0.437500),
  89. COEFF_NORM(0.437500), COEFF_NORM(-0.397384), COEFF_NORM(-0.040116),
  90. 0, 0, 0, /* 10'/11'/12' */
  91. 0, 0, 0, /* 20'/21'/22' */
  92. 64, 512, 512, /* offset */
  93. 0, 0, 0 /* mode, right_shift, clip_en */
  94. };
  95. /* eotf matrix: bypass */
  96. static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
  97. EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0),
  98. EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0), EOTF_COEFF_NORM(0.0),
  99. EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(0.0), EOTF_COEFF_NORM(1.0),
  100. EOTF_COEFF_RIGHTSHIFT /* right shift */
  101. };
  102. static void meson_viu_set_g12a_osd1_matrix(struct meson_vpu_priv *priv,
  103. int *m, bool csc_on)
  104. {
  105. /* VPP WRAP OSD1 matrix */
  106. writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
  107. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET0_1));
  108. writel(m[2] & 0xfff,
  109. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_PRE_OFFSET2));
  110. writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
  111. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF00_01));
  112. writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
  113. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF02_10));
  114. writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
  115. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
  116. writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
  117. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
  118. writel((m[11] & 0x1fff) << 16,
  119. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF22));
  120. writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
  121. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET0_1));
  122. writel(m[20] & 0xfff,
  123. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_OFFSET2));
  124. writel_bits(BIT(0), csc_on ? BIT(0) : 0,
  125. priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_EN_CTRL));
  126. }
  127. static void meson_viu_set_osd_matrix(struct meson_vpu_priv *priv,
  128. enum viu_matrix_sel_e m_select,
  129. int *m, bool csc_on)
  130. {
  131. if (m_select == VIU_MATRIX_OSD) {
  132. /* osd matrix, VIU_MATRIX_0 */
  133. writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
  134. priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
  135. writel(m[2] & 0xfff,
  136. priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
  137. writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
  138. priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
  139. writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
  140. priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
  141. writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
  142. priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
  143. writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
  144. priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
  145. if (m[21]) {
  146. writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
  147. priv->io_base +
  148. _REG(VIU_OSD1_MATRIX_COEF22_30));
  149. writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
  150. priv->io_base +
  151. _REG(VIU_OSD1_MATRIX_COEF31_32));
  152. writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
  153. priv->io_base +
  154. _REG(VIU_OSD1_MATRIX_COEF40_41));
  155. writel(m[17] & 0x1fff, priv->io_base +
  156. _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
  157. } else {
  158. writel((m[11] & 0x1fff) << 16, priv->io_base +
  159. _REG(VIU_OSD1_MATRIX_COEF22_30));
  160. }
  161. writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
  162. priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
  163. writel(m[20] & 0xfff,
  164. priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
  165. writel_bits(3 << 30, m[21] << 30,
  166. priv->io_base +
  167. _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
  168. writel_bits(7 << 16, m[22] << 16,
  169. priv->io_base +
  170. _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
  171. /* 23 reserved for clipping control */
  172. writel_bits(BIT(0), csc_on ? BIT(0) : 0,
  173. priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
  174. writel_bits(BIT(1), 0,
  175. priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
  176. } else if (m_select == VIU_MATRIX_OSD_EOTF) {
  177. int i;
  178. /* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
  179. for (i = 0; i < 5; i++)
  180. writel(((m[i * 2] & 0x1fff) << 16) |
  181. (m[i * 2 + 1] & 0x1fff), priv->io_base +
  182. _REG(VIU_OSD1_EOTF_CTL + i + 1));
  183. writel_bits(BIT(30), csc_on ? BIT(30) : 0,
  184. priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
  185. writel_bits(BIT(31), csc_on ? BIT(31) : 0,
  186. priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
  187. }
  188. }
  189. #define OSD_EOTF_LUT_SIZE 33
  190. #define OSD_OETF_LUT_SIZE 41
  191. static void meson_viu_set_osd_lut(struct meson_vpu_priv *priv,
  192. enum viu_lut_sel_e lut_sel,
  193. unsigned int *r_map, unsigned int *g_map,
  194. unsigned int *b_map,
  195. bool csc_on)
  196. {
  197. unsigned int addr_port;
  198. unsigned int data_port;
  199. unsigned int ctrl_port;
  200. int i;
  201. if (lut_sel == VIU_LUT_OSD_EOTF) {
  202. addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
  203. data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
  204. ctrl_port = VIU_OSD1_EOTF_CTL;
  205. } else if (lut_sel == VIU_LUT_OSD_OETF) {
  206. addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
  207. data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
  208. ctrl_port = VIU_OSD1_OETF_CTL;
  209. } else {
  210. return;
  211. }
  212. if (lut_sel == VIU_LUT_OSD_OETF) {
  213. writel(0, priv->io_base + _REG(addr_port));
  214. for (i = 0; i < 20; i++)
  215. writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
  216. priv->io_base + _REG(data_port));
  217. writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
  218. priv->io_base + _REG(data_port));
  219. for (i = 0; i < 20; i++)
  220. writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
  221. priv->io_base + _REG(data_port));
  222. for (i = 0; i < 20; i++)
  223. writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
  224. priv->io_base + _REG(data_port));
  225. writel(b_map[OSD_OETF_LUT_SIZE - 1],
  226. priv->io_base + _REG(data_port));
  227. if (csc_on)
  228. writel_bits(0x7 << 29, 7 << 29,
  229. priv->io_base + _REG(ctrl_port));
  230. else
  231. writel_bits(0x7 << 29, 0,
  232. priv->io_base + _REG(ctrl_port));
  233. } else if (lut_sel == VIU_LUT_OSD_EOTF) {
  234. writel(0, priv->io_base + _REG(addr_port));
  235. for (i = 0; i < 20; i++)
  236. writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
  237. priv->io_base + _REG(data_port));
  238. writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
  239. priv->io_base + _REG(data_port));
  240. for (i = 0; i < 20; i++)
  241. writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
  242. priv->io_base + _REG(data_port));
  243. for (i = 0; i < 20; i++)
  244. writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
  245. priv->io_base + _REG(data_port));
  246. writel(b_map[OSD_EOTF_LUT_SIZE - 1],
  247. priv->io_base + _REG(data_port));
  248. if (csc_on)
  249. writel_bits(7 << 27, 7 << 27,
  250. priv->io_base + _REG(ctrl_port));
  251. else
  252. writel_bits(7 << 27, 0,
  253. priv->io_base + _REG(ctrl_port));
  254. writel_bits(BIT(31), BIT(31),
  255. priv->io_base + _REG(ctrl_port));
  256. }
  257. }
  258. /* eotf lut: linear */
  259. static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
  260. 0x0000, 0x0200, 0x0400, 0x0600,
  261. 0x0800, 0x0a00, 0x0c00, 0x0e00,
  262. 0x1000, 0x1200, 0x1400, 0x1600,
  263. 0x1800, 0x1a00, 0x1c00, 0x1e00,
  264. 0x2000, 0x2200, 0x2400, 0x2600,
  265. 0x2800, 0x2a00, 0x2c00, 0x2e00,
  266. 0x3000, 0x3200, 0x3400, 0x3600,
  267. 0x3800, 0x3a00, 0x3c00, 0x3e00,
  268. 0x4000
  269. };
  270. /* osd oetf lut: linear */
  271. static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
  272. 0, 0, 0, 0,
  273. 0, 32, 64, 96,
  274. 128, 160, 196, 224,
  275. 256, 288, 320, 352,
  276. 384, 416, 448, 480,
  277. 512, 544, 576, 608,
  278. 640, 672, 704, 736,
  279. 768, 800, 832, 864,
  280. 896, 928, 960, 992,
  281. 1023, 1023, 1023, 1023,
  282. 1023
  283. };
  284. static void meson_viu_load_matrix(struct meson_vpu_priv *priv)
  285. {
  286. /* eotf lut bypass */
  287. meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
  288. eotf_33_linear_mapping, /* R */
  289. eotf_33_linear_mapping, /* G */
  290. eotf_33_linear_mapping, /* B */
  291. false);
  292. /* eotf matrix bypass */
  293. meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
  294. eotf_bypass_coeff,
  295. false);
  296. /* oetf lut bypass */
  297. meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
  298. oetf_41_linear_mapping, /* R */
  299. oetf_41_linear_mapping, /* G */
  300. oetf_41_linear_mapping, /* B */
  301. false);
  302. /* osd matrix RGB709 to YUV709 limit */
  303. meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
  304. RGB709_to_YUV709l_coeff,
  305. true);
  306. }
  307. static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length)
  308. {
  309. u32 val = (((length & 0x80) % 24) / 12);
  310. return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31));
  311. }
  312. void meson_vpu_init(struct udevice *dev)
  313. {
  314. struct meson_vpu_priv *priv = dev_get_priv(dev);
  315. u32 reg;
  316. /*
  317. * Slave dc0 and dc5 connected to master port 1.
  318. * By default other slaves are connected to master port 0.
  319. */
  320. reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) |
  321. VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1);
  322. writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C1));
  323. /* Slave dc0 connected to master port 1 */
  324. reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1);
  325. writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L1C2));
  326. /* Slave dc4 and dc7 connected to master port 1 */
  327. reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) |
  328. VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1);
  329. writel(reg, priv->io_base + _REG(VPU_RDARB_MODE_L2C1));
  330. /* Slave dc1 connected to master port 1 */
  331. reg = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1);
  332. writel(reg, priv->io_base + _REG(VPU_WRARB_MODE_L2C1));
  333. /* Disable CVBS VDAC */
  334. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  335. hhi_write(HHI_VDAC_CNTL0_G12A, 0);
  336. hhi_write(HHI_VDAC_CNTL1_G12A, 8);
  337. } else {
  338. hhi_write(HHI_VDAC_CNTL0, 0);
  339. hhi_write(HHI_VDAC_CNTL1, 8);
  340. }
  341. /* Power Down Dacs */
  342. writel(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
  343. /* Disable HDMI PHY */
  344. hhi_write(HHI_HDMI_PHY_CNTL0, 0);
  345. /* Disable HDMI */
  346. writel_bits(VPU_HDMI_ENCI_DATA_TO_HDMI |
  347. VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
  348. priv->io_base + _REG(VPU_HDMI_SETTING));
  349. /* Disable all encoders */
  350. writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
  351. writel(0, priv->io_base + _REG(ENCP_VIDEO_EN));
  352. writel(0, priv->io_base + _REG(ENCL_VIDEO_EN));
  353. /* Disable VSync IRQ */
  354. writel(0, priv->io_base + _REG(VENC_INTCTRL));
  355. /* set dummy data default YUV black */
  356. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
  357. writel(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
  358. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM)) {
  359. writel_bits(0xff << 16, 0xff << 16,
  360. priv->io_base + _REG(VIU_MISC_CTRL1));
  361. writel(VPP_PPS_DUMMY_DATA_MODE,
  362. priv->io_base + _REG(VPP_DOLBY_CTRL));
  363. writel(0x1020080,
  364. priv->io_base + _REG(VPP_DUMMY_DATA1));
  365. } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  366. writel(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
  367. /* Initialize vpu fifo control registers */
  368. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  369. writel(VPP_OFIFO_SIZE_DEFAULT,
  370. priv->io_base + _REG(VPP_OFIFO_SIZE));
  371. else
  372. writel_bits(VPP_OFIFO_SIZE_MASK, 0x77f,
  373. priv->io_base + _REG(VPP_OFIFO_SIZE));
  374. writel(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4),
  375. priv->io_base + _REG(VPP_HOLD_LINES));
  376. if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  377. /* Turn off preblend */
  378. writel_bits(VPP_PREBLEND_ENABLE, 0,
  379. priv->io_base + _REG(VPP_MISC));
  380. /* Turn off POSTBLEND */
  381. writel_bits(VPP_POSTBLEND_ENABLE, 0,
  382. priv->io_base + _REG(VPP_MISC));
  383. /* Force all planes off */
  384. writel_bits(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
  385. VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND |
  386. VPP_VD1_PREBLEND | VPP_VD2_PREBLEND, 0,
  387. priv->io_base + _REG(VPP_MISC));
  388. /* Setup default VD settings */
  389. writel(4096,
  390. priv->io_base + _REG(VPP_PREBLEND_VD1_H_START_END));
  391. writel(4096,
  392. priv->io_base + _REG(VPP_BLEND_VD2_H_START_END));
  393. }
  394. /* Disable Scalers */
  395. writel(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
  396. writel(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
  397. writel(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
  398. writel(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) |
  399. VPP_SC_VD_EN_ENABLE,
  400. priv->io_base + _REG(VPP_SC_MISC));
  401. /* Enable minus black level for vadj1 */
  402. writel(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE,
  403. priv->io_base + _REG(VPP_VADJ_CTRL));
  404. /* Write in the proper filter coefficients. */
  405. meson_vpp_write_scaling_filter_coefs(priv,
  406. vpp_filter_coefs_4point_bspline, false);
  407. meson_vpp_write_scaling_filter_coefs(priv,
  408. vpp_filter_coefs_4point_bspline, true);
  409. /* Write the VD proper filter coefficients. */
  410. meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
  411. false);
  412. meson_vpp_write_vd_scaling_filter_coefs(priv, vpp_filter_coefs_bicubic,
  413. true);
  414. /* Disable OSDs */
  415. writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
  416. priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
  417. writel_bits(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0,
  418. priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
  419. /* On GXL/GXM, Use the 10bit HDR conversion matrix */
  420. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
  421. meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
  422. meson_viu_load_matrix(priv);
  423. else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  424. meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
  425. true);
  426. /* Initialize OSD1 fifo control register */
  427. reg = VIU_OSD_DDR_PRIORITY_URGENT |
  428. VIU_OSD_HOLD_FIFO_LINES(4) |
  429. VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */
  430. VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */
  431. VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */
  432. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
  433. reg |= meson_viu_osd_burst_length_reg(32);
  434. else
  435. reg |= meson_viu_osd_burst_length_reg(64);
  436. writel(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
  437. writel(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
  438. /* Set OSD alpha replace value */
  439. writel_bits(0xff << OSD_REPLACE_SHIFT,
  440. 0xff << OSD_REPLACE_SHIFT,
  441. priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
  442. writel_bits(0xff << OSD_REPLACE_SHIFT,
  443. 0xff << OSD_REPLACE_SHIFT,
  444. priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
  445. /* Disable VD1 AFBC */
  446. /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/
  447. writel_bits(VIU_CTRL0_VD1_AFBC_MASK, 0,
  448. priv->io_base + _REG(VIU_MISC_CTRL0));
  449. writel(0, priv->io_base + _REG(AFBC_ENABLE));
  450. writel(0x00FF00C0,
  451. priv->io_base + _REG(VD1_IF0_LUMA_FIFO_SIZE));
  452. writel(0x00FF00C0,
  453. priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
  454. if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
  455. writel(VIU_OSD_BLEND_REORDER(0, 1) |
  456. VIU_OSD_BLEND_REORDER(1, 0) |
  457. VIU_OSD_BLEND_REORDER(2, 0) |
  458. VIU_OSD_BLEND_REORDER(3, 0) |
  459. VIU_OSD_BLEND_DIN_EN(1) |
  460. VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
  461. VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
  462. VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
  463. VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
  464. VIU_OSD_BLEND_HOLD_LINES(4),
  465. priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
  466. writel(OSD_BLEND_PATH_SEL_ENABLE,
  467. priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
  468. writel(OSD_BLEND_PATH_SEL_ENABLE,
  469. priv->io_base + _REG(OSD2_BLEND_SRC_CTRL));
  470. writel(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
  471. writel(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL));
  472. writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0));
  473. writel(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA));
  474. writel_bits(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc),
  475. priv->io_base + _REG(DOLBY_PATH_CTRL));
  476. }
  477. }