File Index
Files and directories
Sign in
FILE

dpu_hw_cdm.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2023, The Linux Foundation. All rights reserved.
  4 */
  5
  6#include <linux/bitfield.h>
  7
  8#include <drm/drm_managed.h>
  9
 10#include "dpu_hw_mdss.h"
 11#include "dpu_hw_util.h"
 12#include "dpu_hw_catalog.h"
 13#include "dpu_hw_cdm.h"
 14#include "dpu_kms.h"
 15
 16#define CDM_CSC_10_OPMODE                  0x000
 17#define CDM_CSC_10_BASE                    0x004
 18
 19#define CDM_CDWN2_OP_MODE                  0x100
 20#define CDM_CDWN2_CLAMP_OUT                0x104
 21#define CDM_CDWN2_PARAMS_3D_0              0x108
 22#define CDM_CDWN2_PARAMS_3D_1              0x10C
 23#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
 24#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
 25#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
 26#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
 27#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
 28#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
 29#define CDM_CDWN2_COEFF_COSITE_V           0x128
 30#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
 31#define CDM_CDWN2_OUT_SIZE                 0x130
 32
 33#define CDM_HDMI_PACK_OP_MODE              0x200
 34#define CDM_CSC_10_MATRIX_COEFF_0          0x004
 35
 36#define CDM_MUX                            0x224
 37
 38/* CDM CDWN2 sub-block bit definitions */
 39#define CDM_CDWN2_OP_MODE_EN                  BIT(0)
 40#define CDM_CDWN2_OP_MODE_ENABLE_H            BIT(1)
 41#define CDM_CDWN2_OP_MODE_ENABLE_V            BIT(2)
 42#define CDM_CDWN2_OP_MODE_BITS_OUT_8BIT       BIT(7)
 43#define CDM_CDWN2_V_PIXEL_METHOD_MASK         GENMASK(6, 5)
 44#define CDM_CDWN2_H_PIXEL_METHOD_MASK         GENMASK(4, 3)
 45
 46/* CDM CSC10 sub-block bit definitions */
 47#define CDM_CSC10_OP_MODE_EN               BIT(0)
 48#define CDM_CSC10_OP_MODE_SRC_FMT_YUV      BIT(1)
 49#define CDM_CSC10_OP_MODE_DST_FMT_YUV      BIT(2)
 50
 51/* CDM HDMI pack sub-block bit definitions */
 52#define CDM_HDMI_PACK_OP_MODE_EN           BIT(0)
 53
 54/*
 55 * Horizontal coefficients for cosite chroma downscale
 56 * s13 representation of coefficients
 57 */
 58static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
 59
 60/*
 61 * Horizontal coefficients for offsite chroma downscale
 62 */
 63static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
 64
 65/*
 66 * Vertical coefficients for cosite chroma downscale
 67 */
 68static u32 cosite_v_coeff[] = {0x00080004};
 69/*
 70 * Vertical coefficients for offsite chroma downscale
 71 */
 72static u32 offsite_v_coeff[] = {0x00060002};
 73
 74static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
 75{
 76	struct dpu_hw_blk_reg_map *c = &ctx->hw;
 77	u32 opmode;
 78	u32 out_size;
 79
 80	switch (cfg->h_cdwn_type) {
 81	case CDM_CDWN_DISABLE:
 82		opmode = 0;
 83		break;
 84	case CDM_CDWN_PIXEL_DROP:
 85		opmode = CDM_CDWN2_OP_MODE_ENABLE_H |
 86				FIELD_PREP(CDM_CDWN2_H_PIXEL_METHOD_MASK,
 87					   CDM_CDWN2_METHOD_PIXEL_DROP);
 88		break;
 89	case CDM_CDWN_AVG:
 90		opmode = CDM_CDWN2_OP_MODE_ENABLE_H |
 91				FIELD_PREP(CDM_CDWN2_H_PIXEL_METHOD_MASK,
 92					   CDM_CDWN2_METHOD_AVG);
 93		break;
 94	case CDM_CDWN_COSITE:
 95		opmode = CDM_CDWN2_OP_MODE_ENABLE_H |
 96				FIELD_PREP(CDM_CDWN2_H_PIXEL_METHOD_MASK,
 97					   CDM_CDWN2_METHOD_COSITE);
 98		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
 99			      cosite_h_coeff[0]);
100		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
101			      cosite_h_coeff[1]);
102		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
103			      cosite_h_coeff[2]);
104		break;
105	case CDM_CDWN_OFFSITE:
106		opmode = CDM_CDWN2_OP_MODE_ENABLE_H |
107				FIELD_PREP(CDM_CDWN2_H_PIXEL_METHOD_MASK, CDM_CDWN2_METHOD_OFFSITE);
108		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
109			      offsite_h_coeff[0]);
110		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
111			      offsite_h_coeff[1]);
112		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
113			      offsite_h_coeff[2]);
114		break;
115	default:
116		DPU_ERROR("%s invalid horz down sampling type\n", __func__);
117		return -EINVAL;
118	}
119
120	switch (cfg->v_cdwn_type) {
121	case CDM_CDWN_DISABLE:
122		/* if its only Horizontal downsample, we dont need to do anything here */
123		break;
124	case CDM_CDWN_PIXEL_DROP:
125		opmode |= CDM_CDWN2_OP_MODE_ENABLE_V |
126				FIELD_PREP(CDM_CDWN2_V_PIXEL_METHOD_MASK,
127					   CDM_CDWN2_METHOD_PIXEL_DROP);
128		break;
129	case CDM_CDWN_AVG:
130		opmode |= CDM_CDWN2_OP_MODE_ENABLE_V |
131				FIELD_PREP(CDM_CDWN2_V_PIXEL_METHOD_MASK,
132					   CDM_CDWN2_METHOD_AVG);
133		break;
134	case CDM_CDWN_COSITE:
135		opmode |= CDM_CDWN2_OP_MODE_ENABLE_V |
136				FIELD_PREP(CDM_CDWN2_V_PIXEL_METHOD_MASK,
137					   CDM_CDWN2_METHOD_COSITE);
138		DPU_REG_WRITE(c,
139			      CDM_CDWN2_COEFF_COSITE_V,
140			      cosite_v_coeff[0]);
141		break;
142	case CDM_CDWN_OFFSITE:
143		opmode |= CDM_CDWN2_OP_MODE_ENABLE_V |
144				FIELD_PREP(CDM_CDWN2_V_PIXEL_METHOD_MASK,
145					   CDM_CDWN2_METHOD_OFFSITE);
146		DPU_REG_WRITE(c,
147			      CDM_CDWN2_COEFF_OFFSITE_V,
148			      offsite_v_coeff[0]);
149		break;
150	default:
151		return -EINVAL;
152	}
153
154	if (cfg->output_bit_depth != CDM_CDWN_OUTPUT_10BIT)
155		opmode |= CDM_CDWN2_OP_MODE_BITS_OUT_8BIT;
156
157	if (cfg->v_cdwn_type || cfg->h_cdwn_type)
158		opmode |= CDM_CDWN2_OP_MODE_EN; /* EN CDWN module */
159	else
160		opmode &= ~CDM_CDWN2_OP_MODE_EN;
161
162	out_size = (cfg->output_width & 0xFFFF) | ((cfg->output_height & 0xFFFF) << 16);
163	DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
164	DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
165	DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT, ((0x3FF << 16) | 0x0));
166
167	return 0;
168}
169
170static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
171{
172	struct dpu_hw_blk_reg_map *c = &ctx->hw;
173	const struct msm_format *fmt;
174	u32 opmode = 0;
175	u32 csc = 0;
176
177	if (!ctx || !cdm)
178		return -EINVAL;
179
180	fmt = cdm->output_fmt;
181
182	if (!MSM_FORMAT_IS_YUV(fmt))
183		return -EINVAL;
184
185	dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, cdm->csc_cfg, true);
186	dpu_hw_cdm_setup_cdwn(ctx, cdm);
187
188	if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
189		if (fmt->chroma_sample == CHROMA_H1V2)
190			return -EINVAL; /*unsupported format */
191		opmode = CDM_HDMI_PACK_OP_MODE_EN;
192		opmode |= (fmt->chroma_sample << 1);
193	}
194
195	csc |= CDM_CSC10_OP_MODE_DST_FMT_YUV;
196	csc &= ~CDM_CSC10_OP_MODE_SRC_FMT_YUV;
197	csc |= CDM_CSC10_OP_MODE_EN;
198
199	if (ctx && ctx->ops.bind_pingpong_blk)
200		ctx->ops.bind_pingpong_blk(ctx, cdm->pp_id);
201
202	DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
203	DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
204	return 0;
205}
206
207static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, const enum dpu_pingpong pp)
208{
209	struct dpu_hw_blk_reg_map *c;
210	int mux_cfg;
211
212	c = &ctx->hw;
213
214	mux_cfg = DPU_REG_READ(c, CDM_MUX);
215	mux_cfg &= ~0xf;
216
217	if (pp >= PINGPONG_CWB_0)
218		mux_cfg |= 0xd;
219	else if (pp)
220		mux_cfg |= (pp - PINGPONG_0) & 0x7;
221	else
222		mux_cfg |= 0xf;
223
224	DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
225}
226
227/**
228 * dpu_hw_cdm_init - initializes the cdm hw driver object.
229 * should be called once before accessing every cdm.
230 * @dev: DRM device handle
231 * @cfg: CDM catalog entry for which driver object is required
232 * @addr :   mapped register io address of MDSS
233 * @mdss_rev: mdss hw core revision
234 */
235struct dpu_hw_cdm *dpu_hw_cdm_init(struct drm_device *dev,
236				   const struct dpu_cdm_cfg *cfg, void __iomem *addr,
237				   const struct dpu_mdss_version *mdss_rev)
238{
239	struct dpu_hw_cdm *c;
240
241	c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
242	if (!c)
243		return ERR_PTR(-ENOMEM);
244
245	c->hw.blk_addr = addr + cfg->base;
246	c->hw.log_mask = DPU_DBG_MASK_CDM;
247
248	/* Assign ops */
249	c->idx = cfg->id;
250	c->caps = cfg;
251
252	c->ops.enable = dpu_hw_cdm_enable;
253	if (mdss_rev->core_major_ver >= 5)
254		c->ops.bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
255
256	return c;
257}
~/ Read-only file preview.