sde_hw_dsc.c 6.5 KB

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