sde_hw_dsc.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  4. */
  5. #include "sde_hw_mdss.h"
  6. #include "sde_hwio.h"
  7. #include "sde_hw_catalog.h"
  8. #include "sde_hw_dsc.h"
  9. #include "sde_hw_pingpong.h"
  10. #include "sde_dbg.h"
  11. #include "sde_kms.h"
  12. #include "sde_hw_dsc_1_2.h"
  13. #define DSC_COMMON_MODE 0x000
  14. #define DSC_ENC 0X004
  15. #define DSC_PICTURE 0x008
  16. #define DSC_SLICE 0x00C
  17. #define DSC_CHUNK_SIZE 0x010
  18. #define DSC_DELAY 0x014
  19. #define DSC_SCALE_INITIAL 0x018
  20. #define DSC_SCALE_DEC_INTERVAL 0x01C
  21. #define DSC_SCALE_INC_INTERVAL 0x020
  22. #define DSC_FIRST_LINE_BPG_OFFSET 0x024
  23. #define DSC_BPG_OFFSET 0x028
  24. #define DSC_DSC_OFFSET 0x02C
  25. #define DSC_FLATNESS 0x030
  26. #define DSC_RC_MODEL_SIZE 0x034
  27. #define DSC_RC 0x038
  28. #define DSC_RC_BUF_THRESH 0x03C
  29. #define DSC_RANGE_MIN_QP 0x074
  30. #define DSC_RANGE_MAX_QP 0x0B0
  31. #define DSC_RANGE_BPG_OFFSET 0x0EC
  32. #define DSC_CTL_BLOCK_SIZE 0x300
  33. #define DSC_CTL(m) \
  34. (((m == DSC_NONE) || (m >= DSC_MAX)) ? 0 : (0x1800 - 0x3FC * (m - 1)))
  35. static void sde_hw_dsc_disable(struct sde_hw_dsc *dsc)
  36. {
  37. struct sde_hw_blk_reg_map *dsc_c = &dsc->hw;
  38. SDE_REG_WRITE(dsc_c, DSC_COMMON_MODE, 0);
  39. }
  40. static void sde_hw_dsc_config(struct sde_hw_dsc *hw_dsc,
  41. struct msm_display_dsc_info *dsc, u32 mode,
  42. bool ich_reset_override)
  43. {
  44. u32 data;
  45. u32 initial_lines = dsc->initial_lines;
  46. struct sde_hw_blk_reg_map *dsc_c = &hw_dsc->hw;
  47. SDE_REG_WRITE(dsc_c, DSC_COMMON_MODE, mode);
  48. data = 0;
  49. if (ich_reset_override)
  50. data = 3 << 28;
  51. data |= (initial_lines << 20);
  52. data |= (dsc->slice_last_group_size << 18);
  53. /* integer bpp support only */
  54. data |= (dsc->config.bits_per_pixel << 8);
  55. data |= (dsc->config.block_pred_enable << 7);
  56. data |= (dsc->config.line_buf_depth << 3);
  57. data |= (dsc->config.simple_422 << 2);
  58. data |= (dsc->config.convert_rgb << 1);
  59. if (dsc->config.bits_per_component == 10)
  60. data |= BIT(0);
  61. SDE_REG_WRITE(dsc_c, DSC_ENC, data);
  62. data = dsc->config.pic_width << 16;
  63. data |= dsc->config.pic_height;
  64. SDE_REG_WRITE(dsc_c, DSC_PICTURE, data);
  65. data = dsc->config.slice_width << 16;
  66. data |= dsc->config.slice_height;
  67. SDE_REG_WRITE(dsc_c, DSC_SLICE, data);
  68. data = dsc->config.slice_chunk_size << 16;
  69. SDE_REG_WRITE(dsc_c, DSC_CHUNK_SIZE, data);
  70. data = dsc->config.initial_dec_delay << 16;
  71. data |= dsc->config.initial_xmit_delay;
  72. SDE_REG_WRITE(dsc_c, DSC_DELAY, data);
  73. data = dsc->config.initial_scale_value;
  74. SDE_REG_WRITE(dsc_c, DSC_SCALE_INITIAL, data);
  75. data = dsc->config.scale_decrement_interval;
  76. SDE_REG_WRITE(dsc_c, DSC_SCALE_DEC_INTERVAL, data);
  77. data = dsc->config.scale_increment_interval;
  78. SDE_REG_WRITE(dsc_c, DSC_SCALE_INC_INTERVAL, data);
  79. data = dsc->config.first_line_bpg_offset;
  80. SDE_REG_WRITE(dsc_c, DSC_FIRST_LINE_BPG_OFFSET, data);
  81. data = dsc->config.nfl_bpg_offset << 16;
  82. data |= dsc->config.slice_bpg_offset;
  83. SDE_REG_WRITE(dsc_c, DSC_BPG_OFFSET, data);
  84. data = dsc->config.initial_offset << 16;
  85. data |= dsc->config.final_offset;
  86. SDE_REG_WRITE(dsc_c, DSC_DSC_OFFSET, data);
  87. data = dsc->det_thresh_flatness << 10;
  88. data |= dsc->config.flatness_max_qp << 5;
  89. data |= dsc->config.flatness_min_qp;
  90. SDE_REG_WRITE(dsc_c, DSC_FLATNESS, data);
  91. data = dsc->config.rc_model_size;
  92. SDE_REG_WRITE(dsc_c, DSC_RC_MODEL_SIZE, data);
  93. data = dsc->config.rc_tgt_offset_low << 18;
  94. data |= dsc->config.rc_tgt_offset_high << 14;
  95. data |= dsc->config.rc_quant_incr_limit1 << 9;
  96. data |= dsc->config.rc_quant_incr_limit0 << 4;
  97. data |= dsc->config.rc_edge_factor;
  98. SDE_REG_WRITE(dsc_c, DSC_RC, data);
  99. }
  100. static void sde_hw_dsc_config_thresh(struct sde_hw_dsc *hw_dsc,
  101. struct msm_display_dsc_info *dsc)
  102. {
  103. u16 *lp;
  104. int i;
  105. struct sde_hw_blk_reg_map *dsc_c = &hw_dsc->hw;
  106. u32 off = 0x0;
  107. struct drm_dsc_rc_range_parameters *rc =
  108. dsc->config.rc_range_params;
  109. lp = dsc->config.rc_buf_thresh;
  110. off = DSC_RC_BUF_THRESH;
  111. for (i = 0; i < DSC_NUM_BUF_RANGES - 1; i++) {
  112. SDE_REG_WRITE(dsc_c, off, *lp++);
  113. off += 4;
  114. }
  115. off = DSC_RANGE_MIN_QP;
  116. for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
  117. SDE_REG_WRITE(dsc_c, off, rc[i].range_min_qp);
  118. off += 4;
  119. }
  120. off = DSC_RANGE_MAX_QP;
  121. for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
  122. SDE_REG_WRITE(dsc_c, off, rc[i].range_max_qp);
  123. off += 4;
  124. }
  125. off = DSC_RANGE_BPG_OFFSET;
  126. for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
  127. SDE_REG_WRITE(dsc_c, off, rc[i].range_bpg_offset);
  128. off += 4;
  129. }
  130. }
  131. static void sde_hw_dsc_bind_pingpong_blk(
  132. struct sde_hw_dsc *hw_dsc,
  133. bool enable,
  134. const enum sde_pingpong pp)
  135. {
  136. struct sde_hw_blk_reg_map *c;
  137. int mux_cfg = 0xF;
  138. u32 dsc_ctl_offset;
  139. if (!hw_dsc)
  140. return;
  141. c = &hw_dsc->hw;
  142. dsc_ctl_offset = DSC_CTL(hw_dsc->idx);
  143. if (enable)
  144. mux_cfg = (pp - PINGPONG_0) & 0x7;
  145. if (dsc_ctl_offset)
  146. SDE_REG_WRITE(c, dsc_ctl_offset, mux_cfg);
  147. }
  148. static struct sde_dsc_cfg *_dsc_offset(enum sde_dsc dsc,
  149. struct sde_mdss_cfg *m,
  150. void __iomem *addr,
  151. struct sde_hw_blk_reg_map *b)
  152. {
  153. int i;
  154. for (i = 0; i < m->dsc_count; i++) {
  155. if (dsc == m->dsc[i].id) {
  156. b->base_off = addr;
  157. b->blk_off = m->dsc[i].base;
  158. b->length = m->dsc[i].len;
  159. b->hwversion = m->hwversion;
  160. b->log_mask = SDE_DBG_MASK_DSC;
  161. return &m->dsc[i];
  162. }
  163. }
  164. return NULL;
  165. }
  166. static void _setup_dsc_ops(struct sde_hw_dsc_ops *ops,
  167. unsigned long features)
  168. {
  169. ops->dsc_disable = sde_hw_dsc_disable;
  170. ops->dsc_config = sde_hw_dsc_config;
  171. ops->dsc_config_thresh = sde_hw_dsc_config_thresh;
  172. if (test_bit(SDE_DSC_OUTPUT_CTRL, &features))
  173. ops->bind_pingpong_blk = sde_hw_dsc_bind_pingpong_blk;
  174. };
  175. static struct sde_hw_blk_ops sde_hw_ops = {
  176. .start = NULL,
  177. .stop = NULL,
  178. };
  179. struct sde_hw_dsc *sde_hw_dsc_init(enum sde_dsc idx,
  180. void __iomem *addr,
  181. struct sde_mdss_cfg *m)
  182. {
  183. struct sde_hw_dsc *c;
  184. struct sde_dsc_cfg *cfg;
  185. u32 dsc_ctl_offset;
  186. int rc = -EINVAL;
  187. c = kzalloc(sizeof(*c), GFP_KERNEL);
  188. if (!c)
  189. return ERR_PTR(-ENOMEM);
  190. cfg = _dsc_offset(idx, m, addr, &c->hw);
  191. if (IS_ERR_OR_NULL(cfg)) {
  192. kfree(c);
  193. return ERR_PTR(-EINVAL);
  194. }
  195. c->idx = idx;
  196. c->caps = cfg;
  197. if (test_bit(SDE_DSC_HW_REV_1_1, &c->caps->features)) {
  198. _setup_dsc_ops(&c->ops, c->caps->features);
  199. sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name,
  200. c->hw.blk_off,
  201. c->hw.blk_off + c->hw.length,
  202. c->hw.xin_id);
  203. if ((c->idx == DSC_0) &&
  204. test_bit(SDE_DSC_OUTPUT_CTRL, &cfg->features)) {
  205. dsc_ctl_offset = DSC_CTL(c->idx);
  206. sde_dbg_reg_register_dump_range(SDE_DBG_NAME,
  207. "dsc_ctl",
  208. c->hw.blk_off + dsc_ctl_offset,
  209. c->hw.blk_off + dsc_ctl_offset +
  210. DSC_CTL_BLOCK_SIZE,
  211. c->hw.xin_id);
  212. }
  213. } else if (test_bit(SDE_DSC_HW_REV_1_2, &c->caps->features)) {
  214. char blk_name[32];
  215. sde_dsc1_2_setup_ops(&c->ops, c->caps->features);
  216. sde_dbg_reg_register_dump_range(SDE_DBG_NAME, cfg->name,
  217. c->hw.blk_off,
  218. c->hw.blk_off + c->hw.length,
  219. c->hw.xin_id);
  220. snprintf(blk_name, sizeof(blk_name), "dsc_enc_%u",
  221. c->idx - DSC_0);
  222. sde_dbg_reg_register_dump_range(SDE_DBG_NAME,
  223. blk_name,
  224. c->hw.blk_off + c->caps->sblk->enc.base,
  225. c->hw.blk_off + c->caps->sblk->enc.base +
  226. c->caps->sblk->enc.len,
  227. c->hw.xin_id);
  228. snprintf(blk_name, sizeof(blk_name), "dsc_ctl_%u",
  229. c->idx - DSC_0);
  230. sde_dbg_reg_register_dump_range(SDE_DBG_NAME,
  231. blk_name,
  232. c->hw.blk_off + c->caps->sblk->ctl.base,
  233. c->hw.blk_off + c->caps->sblk->ctl.base +
  234. c->caps->sblk->ctl.len,
  235. c->hw.xin_id);
  236. } else {
  237. SDE_ERROR("failed to setup ops\n");
  238. goto blk_init_error;
  239. }
  240. rc = sde_hw_blk_init(&c->base, SDE_HW_BLK_DSC, idx, &sde_hw_ops);
  241. if (rc) {
  242. SDE_ERROR("failed to init hw blk %d\n", rc);
  243. goto blk_init_error;
  244. }
  245. return c;
  246. blk_init_error:
  247. kfree(c);
  248. return ERR_PTR(rc);
  249. }
  250. void sde_hw_dsc_destroy(struct sde_hw_dsc *dsc)
  251. {
  252. if (dsc)
  253. sde_hw_blk_destroy(&dsc->base);
  254. kfree(dsc);
  255. }