File Index
Files and directories
Sign in
FILE

dpu_hw_dsc_1_2.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  4 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved
  5 */
  6
  7#include <drm/drm_managed.h>
  8
  9#include <drm/display/drm_dsc_helper.h>
 10
 11#include "dpu_kms.h"
 12#include "dpu_hw_catalog.h"
 13#include "dpu_hwio.h"
 14#include "dpu_hw_mdss.h"
 15#include "dpu_hw_dsc.h"
 16
 17#define DSC_CMN_MAIN_CNF           0x00
 18
 19/* DPU_DSC_ENC register offsets */
 20#define ENC_DF_CTRL                0x00
 21#define ENC_GENERAL_STATUS         0x04
 22#define ENC_HSLICE_STATUS          0x08
 23#define ENC_OUT_STATUS             0x0C
 24#define ENC_INT_STAT               0x10
 25#define ENC_INT_CLR                0x14
 26#define ENC_INT_MASK               0x18
 27#define DSC_MAIN_CONF              0x30
 28#define DSC_PICTURE_SIZE           0x34
 29#define DSC_SLICE_SIZE             0x38
 30#define DSC_MISC_SIZE              0x3C
 31#define DSC_HRD_DELAYS             0x40
 32#define DSC_RC_SCALE               0x44
 33#define DSC_RC_SCALE_INC_DEC       0x48
 34#define DSC_RC_OFFSETS_1           0x4C
 35#define DSC_RC_OFFSETS_2           0x50
 36#define DSC_RC_OFFSETS_3           0x54
 37#define DSC_RC_OFFSETS_4           0x58
 38#define DSC_FLATNESS_QP            0x5C
 39#define DSC_RC_MODEL_SIZE          0x60
 40#define DSC_RC_CONFIG              0x64
 41#define DSC_RC_BUF_THRESH_0        0x68
 42#define DSC_RC_BUF_THRESH_1        0x6C
 43#define DSC_RC_BUF_THRESH_2        0x70
 44#define DSC_RC_BUF_THRESH_3        0x74
 45#define DSC_RC_MIN_QP_0            0x78
 46#define DSC_RC_MIN_QP_1            0x7C
 47#define DSC_RC_MIN_QP_2            0x80
 48#define DSC_RC_MAX_QP_0            0x84
 49#define DSC_RC_MAX_QP_1            0x88
 50#define DSC_RC_MAX_QP_2            0x8C
 51#define DSC_RC_RANGE_BPG_OFFSETS_0 0x90
 52#define DSC_RC_RANGE_BPG_OFFSETS_1 0x94
 53#define DSC_RC_RANGE_BPG_OFFSETS_2 0x98
 54
 55/* DPU_DSC_CTL register offsets */
 56#define DSC_CTL                    0x00
 57#define DSC_CFG                    0x04
 58#define DSC_DATA_IN_SWAP           0x08
 59#define DSC_CLK_CTRL               0x0C
 60
 61static int _dsc_calc_output_buf_max_addr(struct dpu_hw_dsc *hw_dsc, int num_softslice)
 62{
 63	int max_addr = 2400 / num_softslice;
 64
 65	if (hw_dsc->caps->features & BIT(DPU_DSC_NATIVE_42x_EN))
 66		max_addr /= 2;
 67
 68	return max_addr - 1;
 69};
 70
 71static void dpu_hw_dsc_disable_1_2(struct dpu_hw_dsc *hw_dsc)
 72{
 73	struct dpu_hw_blk_reg_map *hw;
 74	const struct dpu_dsc_sub_blks *sblk;
 75
 76	if (!hw_dsc)
 77		return;
 78
 79	hw = &hw_dsc->hw;
 80	sblk = hw_dsc->caps->sblk;
 81	DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, 0);
 82
 83	DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, 0);
 84	DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, 0);
 85}
 86
 87static void dpu_hw_dsc_config_1_2(struct dpu_hw_dsc *hw_dsc,
 88				  struct drm_dsc_config *dsc,
 89				  u32 mode,
 90				  u32 initial_lines)
 91{
 92	struct dpu_hw_blk_reg_map *hw;
 93	const struct dpu_dsc_sub_blks *sblk;
 94	u32 data = 0;
 95	u32 det_thresh_flatness;
 96	u32 num_active_slice_per_enc;
 97	u32 bpp;
 98
 99	if (!hw_dsc || !dsc)
100		return;
101
102	hw = &hw_dsc->hw;
103
104	sblk = hw_dsc->caps->sblk;
105
106	if (mode & DSC_MODE_SPLIT_PANEL)
107		data |= BIT(0);
108
109	if (mode & DSC_MODE_MULTIPLEX)
110		data |= BIT(1);
111
112	num_active_slice_per_enc = dsc->slice_count;
113	if (mode & DSC_MODE_MULTIPLEX)
114		num_active_slice_per_enc = dsc->slice_count / 2;
115
116	data |= (num_active_slice_per_enc & 0x3) << 7;
117
118	DPU_REG_WRITE(hw, DSC_CMN_MAIN_CNF, data);
119
120	data = (initial_lines & 0xff);
121
122	if (mode & DSC_MODE_VIDEO)
123		data |= BIT(9);
124
125	data |= (_dsc_calc_output_buf_max_addr(hw_dsc, num_active_slice_per_enc) << 18);
126
127	DPU_REG_WRITE(hw, sblk->enc.base + ENC_DF_CTRL, data);
128
129	data = (dsc->dsc_version_minor & 0xf) << 28;
130	if (dsc->dsc_version_minor == 0x2) {
131		if (dsc->native_422)
132			data |= BIT(22);
133		if (dsc->native_420)
134			data |= BIT(21);
135	}
136
137	bpp = dsc->bits_per_pixel;
138	/* as per hw requirement bpp should be programmed
139	 * twice the actual value in case of 420 or 422 encoding
140	 */
141	if (dsc->native_422 || dsc->native_420)
142		bpp = 2 * bpp;
143
144	data |= bpp << 10;
145
146	if (dsc->block_pred_enable)
147		data |= BIT(20);
148
149	if (dsc->convert_rgb)
150		data |= BIT(4);
151
152	data |= (dsc->line_buf_depth & 0xf) << 6;
153	data |= dsc->bits_per_component & 0xf;
154
155	DPU_REG_WRITE(hw, sblk->enc.base + DSC_MAIN_CONF, data);
156
157	data = (dsc->pic_width & 0xffff) |
158		((dsc->pic_height & 0xffff) << 16);
159
160	DPU_REG_WRITE(hw, sblk->enc.base + DSC_PICTURE_SIZE, data);
161
162	data = (dsc->slice_width & 0xffff) |
163		((dsc->slice_height & 0xffff) << 16);
164
165	DPU_REG_WRITE(hw, sblk->enc.base + DSC_SLICE_SIZE, data);
166
167	DPU_REG_WRITE(hw, sblk->enc.base + DSC_MISC_SIZE,
168		      (dsc->slice_chunk_size) & 0xffff);
169
170	data = (dsc->initial_xmit_delay & 0xffff) |
171		((dsc->initial_dec_delay & 0xffff) << 16);
172
173	DPU_REG_WRITE(hw, sblk->enc.base + DSC_HRD_DELAYS, data);
174
175	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE,
176		      dsc->initial_scale_value & 0x3f);
177
178	data = (dsc->scale_increment_interval & 0xffff) |
179		((dsc->scale_decrement_interval & 0x7ff) << 16);
180
181	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_SCALE_INC_DEC, data);
182
183	data = (dsc->first_line_bpg_offset & 0x1f) |
184		((dsc->second_line_bpg_offset & 0x1f) << 5);
185
186	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_1, data);
187
188	data = (dsc->nfl_bpg_offset & 0xffff) |
189		((dsc->slice_bpg_offset & 0xffff) << 16);
190
191	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_2, data);
192
193	data = (dsc->initial_offset & 0xffff) |
194		((dsc->final_offset & 0xffff) << 16);
195
196	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_3, data);
197
198	data = (dsc->nsl_bpg_offset & 0xffff) |
199		((dsc->second_line_offset_adj & 0xffff) << 16);
200
201	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_OFFSETS_4, data);
202
203	det_thresh_flatness = drm_dsc_flatness_det_thresh(dsc);
204	data = (dsc->flatness_min_qp & 0x1f) |
205		((dsc->flatness_max_qp & 0x1f) << 5) |
206		((det_thresh_flatness & 0xff) << 10);
207
208	DPU_REG_WRITE(hw, sblk->enc.base + DSC_FLATNESS_QP, data);
209
210	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MODEL_SIZE,
211		      (dsc->rc_model_size) & 0xffff);
212
213	data = dsc->rc_edge_factor & 0xf;
214	data |= (dsc->rc_quant_incr_limit0 & 0x1f) << 8;
215	data |= (dsc->rc_quant_incr_limit1 & 0x1f) << 13;
216	data |= (dsc->rc_tgt_offset_high & 0xf) << 20;
217	data |= (dsc->rc_tgt_offset_low & 0xf) << 24;
218
219	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_CONFIG, data);
220
221	/* program the dsc wrapper */
222	data = BIT(0); /* encoder enable */
223	if (dsc->native_422)
224		data |= BIT(8);
225	else if (dsc->native_420)
226		data |= BIT(9);
227	if (!dsc->convert_rgb)
228		data |= BIT(10);
229	if (dsc->bits_per_component == 8)
230		data |= BIT(11);
231	if (mode & DSC_MODE_SPLIT_PANEL)
232		data |= BIT(12);
233	if (mode & DSC_MODE_MULTIPLEX)
234		data |= BIT(13);
235	if (!(mode & DSC_MODE_VIDEO))
236		data |= BIT(17);
237
238	DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CFG, data);
239}
240
241static void dpu_hw_dsc_config_thresh_1_2(struct dpu_hw_dsc *hw_dsc,
242					 struct drm_dsc_config *dsc)
243{
244	struct dpu_hw_blk_reg_map *hw;
245	const struct dpu_dsc_sub_blks *sblk;
246	struct drm_dsc_rc_range_parameters *rc;
247
248	if (!hw_dsc || !dsc)
249		return;
250
251	hw = &hw_dsc->hw;
252
253	sblk = hw_dsc->caps->sblk;
254
255	rc = dsc->rc_range_params;
256
257	/*
258	 * With BUF_THRESH -- 14 in total
259	 * each register contains 4 thresh values with the last register
260	 * containing only 2 thresh values
261	 */
262	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_0,
263		      (dsc->rc_buf_thresh[0] << 0) |
264		      (dsc->rc_buf_thresh[1] << 8) |
265		      (dsc->rc_buf_thresh[2] << 16) |
266		      (dsc->rc_buf_thresh[3] << 24));
267	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_1,
268		      (dsc->rc_buf_thresh[4] << 0) |
269		      (dsc->rc_buf_thresh[5] << 8) |
270		      (dsc->rc_buf_thresh[6] << 16) |
271		      (dsc->rc_buf_thresh[7] << 24));
272	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_2,
273		      (dsc->rc_buf_thresh[8] << 0) |
274		      (dsc->rc_buf_thresh[9] << 8) |
275		      (dsc->rc_buf_thresh[10] << 16) |
276		      (dsc->rc_buf_thresh[11] << 24));
277	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_BUF_THRESH_3,
278		      (dsc->rc_buf_thresh[12] << 0) |
279		      (dsc->rc_buf_thresh[13] << 8));
280
281	/*
282	 * with min/max_QP -- 5 bits
283	 * each register contains 5 min_qp or max_qp for total of 15
284	 *
285	 * With BPG_OFFSET -- 6 bits
286	 * each register contains 5 BPG_offset for total of 15
287	 */
288	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_0,
289		      (rc[0].range_min_qp << 0) |
290		      (rc[1].range_min_qp << 5) |
291		      (rc[2].range_min_qp << 10) |
292		      (rc[3].range_min_qp << 15) |
293		      (rc[4].range_min_qp << 20));
294	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_0,
295		      (rc[0].range_max_qp << 0) |
296		      (rc[1].range_max_qp << 5) |
297		      (rc[2].range_max_qp << 10) |
298		      (rc[3].range_max_qp << 15) |
299		      (rc[4].range_max_qp << 20));
300	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_0,
301		      (rc[0].range_bpg_offset << 0) |
302		      (rc[1].range_bpg_offset << 6) |
303		      (rc[2].range_bpg_offset << 12) |
304		      (rc[3].range_bpg_offset << 18) |
305		      (rc[4].range_bpg_offset << 24));
306
307	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_1,
308		      (rc[5].range_min_qp << 0) |
309		      (rc[6].range_min_qp << 5) |
310		      (rc[7].range_min_qp << 10) |
311		      (rc[8].range_min_qp << 15) |
312		      (rc[9].range_min_qp << 20));
313	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_1,
314		      (rc[5].range_max_qp << 0) |
315		      (rc[6].range_max_qp << 5) |
316		      (rc[7].range_max_qp << 10) |
317		      (rc[8].range_max_qp << 15) |
318		      (rc[9].range_max_qp << 20));
319	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_1,
320		      (rc[5].range_bpg_offset << 0) |
321		      (rc[6].range_bpg_offset << 6) |
322		      (rc[7].range_bpg_offset << 12) |
323		      (rc[8].range_bpg_offset << 18) |
324		      (rc[9].range_bpg_offset << 24));
325
326	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MIN_QP_2,
327		      (rc[10].range_min_qp << 0) |
328		      (rc[11].range_min_qp << 5) |
329		      (rc[12].range_min_qp << 10) |
330		      (rc[13].range_min_qp << 15) |
331		      (rc[14].range_min_qp << 20));
332	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_MAX_QP_2,
333		      (rc[10].range_max_qp << 0) |
334		      (rc[11].range_max_qp << 5) |
335		      (rc[12].range_max_qp << 10) |
336		      (rc[13].range_max_qp << 15) |
337		      (rc[14].range_max_qp << 20));
338	DPU_REG_WRITE(hw, sblk->enc.base + DSC_RC_RANGE_BPG_OFFSETS_2,
339		      (rc[10].range_bpg_offset << 0) |
340		      (rc[11].range_bpg_offset << 6) |
341		      (rc[12].range_bpg_offset << 12) |
342		      (rc[13].range_bpg_offset << 18) |
343		      (rc[14].range_bpg_offset << 24));
344}
345
346static void dpu_hw_dsc_bind_pingpong_blk_1_2(struct dpu_hw_dsc *hw_dsc,
347					     const enum dpu_pingpong pp)
348{
349	struct dpu_hw_blk_reg_map *hw;
350	const struct dpu_dsc_sub_blks *sblk;
351	int mux_cfg = 0xf; /* Disabled */
352
353	hw = &hw_dsc->hw;
354
355	sblk = hw_dsc->caps->sblk;
356
357	if (pp)
358		mux_cfg = (pp - PINGPONG_0) & 0x7;
359
360	DPU_REG_WRITE(hw, sblk->ctl.base + DSC_CTL, mux_cfg);
361}
362
363static void _setup_dcs_ops_1_2(struct dpu_hw_dsc_ops *ops)
364{
365	ops->dsc_disable = dpu_hw_dsc_disable_1_2;
366	ops->dsc_config = dpu_hw_dsc_config_1_2;
367	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh_1_2;
368	ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk_1_2;
369}
370
371/**
372 * dpu_hw_dsc_init_1_2() - initializes the v1.2 DSC hw driver object
373 * @dev:  Corresponding device for devres management
374 * @cfg:  DSC catalog entry for which driver object is required
375 * @addr: Mapped register io address of MDP
376 * Returns: Error code or allocated dpu_hw_dsc context
377 */
378struct dpu_hw_dsc *dpu_hw_dsc_init_1_2(struct drm_device *dev,
379				       const struct dpu_dsc_cfg *cfg,
380				       void __iomem *addr)
381{
382	struct dpu_hw_dsc *c;
383
384	c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
385	if (!c)
386		return ERR_PTR(-ENOMEM);
387
388	c->hw.blk_addr = addr + cfg->base;
389	c->hw.log_mask = DPU_DBG_MASK_DSC;
390
391	c->idx = cfg->id;
392	c->caps = cfg;
393	_setup_dcs_ops_1_2(&c->ops);
394
395	return c;
396}
~/ Read-only file preview.