sde_hw_dsc.c 7.7 KB

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