xref: /linux/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/disp.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1 /* SPDX-License-Identifier: MIT
2  *
3  * Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
4  */
5 #include <rm/rm.h>
6 
7 #include <engine/disp.h>
8 #include <engine/disp/outp.h>
9 
10 #include "nvhw/drf.h"
11 
12 #include "nvrm/disp.h"
13 
14 static int
r570_dmac_alloc(struct nvkm_disp * disp,u32 oclass,int inst,u32 put_offset,struct nvkm_gsp_object * dmac)15 r570_dmac_alloc(struct nvkm_disp *disp, u32 oclass, int inst, u32 put_offset,
16 		struct nvkm_gsp_object *dmac)
17 {
18 	NV50VAIO_CHANNELDMA_ALLOCATION_PARAMETERS *args;
19 
20 	args = nvkm_gsp_rm_alloc_get(&disp->rm.object, (oclass << 16) | inst, oclass,
21 				     sizeof(*args), dmac);
22 	if (IS_ERR(args))
23 		return PTR_ERR(args);
24 
25 	args->channelInstance = inst;
26 	args->offset = put_offset;
27 	args->subDeviceId = BIT(0);
28 
29 	return nvkm_gsp_rm_alloc_wr(dmac, args);
30 }
31 
32 static int
r570_disp_chan_set_pushbuf(struct nvkm_disp * disp,s32 oclass,int inst,struct nvkm_memory * memory)33 r570_disp_chan_set_pushbuf(struct nvkm_disp *disp, s32 oclass, int inst, struct nvkm_memory *memory)
34 {
35 	struct nvkm_gsp *gsp = disp->rm.objcom.client->gsp;
36 	NV2080_CTRL_INTERNAL_DISPLAY_CHANNEL_PUSHBUFFER_PARAMS *ctrl;
37 
38 	ctrl = nvkm_gsp_rm_ctrl_get(&gsp->internal.device.subdevice,
39 				    NV2080_CTRL_CMD_INTERNAL_DISPLAY_CHANNEL_PUSHBUFFER,
40 				    sizeof(*ctrl));
41 	if (IS_ERR(ctrl))
42 		return PTR_ERR(ctrl);
43 
44 	if (memory) {
45 		switch (nvkm_memory_target(memory)) {
46 		case NVKM_MEM_TARGET_NCOH:
47 			ctrl->addressSpace = ADDR_SYSMEM;
48 			ctrl->cacheSnoop = 0;
49 			ctrl->pbTargetAperture = PHYS_PCI;
50 			break;
51 		case NVKM_MEM_TARGET_HOST:
52 			ctrl->addressSpace = ADDR_SYSMEM;
53 			ctrl->cacheSnoop = 1;
54 			ctrl->pbTargetAperture = PHYS_PCI_COHERENT;
55 			break;
56 		case NVKM_MEM_TARGET_VRAM:
57 			ctrl->addressSpace = ADDR_FBMEM;
58 			ctrl->pbTargetAperture = PHYS_NVM;
59 			break;
60 		default:
61 			WARN_ON(1);
62 			return -EINVAL;
63 		}
64 
65 		ctrl->physicalAddr = nvkm_memory_addr(memory);
66 		ctrl->limit = nvkm_memory_size(memory) - 1;
67 	}
68 
69 	ctrl->hclass = oclass;
70 	ctrl->channelInstance = inst;
71 	ctrl->valid = ((oclass & 0xff) != 0x7a) ? 1 : 0;
72 	ctrl->subDeviceId = BIT(0);
73 
74 	return nvkm_gsp_rm_ctrl_wr(&gsp->internal.device.subdevice, ctrl);
75 }
76 
77 static int
r570_dp_set_indexed_link_rates(struct nvkm_outp * outp)78 r570_dp_set_indexed_link_rates(struct nvkm_outp *outp)
79 {
80 	NV0073_CTRL_CMD_DP_CONFIG_INDEXED_LINK_RATES_PARAMS *ctrl;
81 	struct nvkm_disp *disp = outp->disp;
82 
83 	if (WARN_ON(outp->dp.rates > ARRAY_SIZE(ctrl->linkRateTbl)))
84 		return -EINVAL;
85 
86 	ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom,
87 				    NV0073_CTRL_CMD_DP_CONFIG_INDEXED_LINK_RATES, sizeof(*ctrl));
88 	if (IS_ERR(ctrl))
89 		return PTR_ERR(ctrl);
90 
91 	ctrl->displayId = BIT(outp->index);
92 	for (int i = 0; i < outp->dp.rates; i++)
93 		ctrl->linkRateTbl[outp->dp.rate[i].dpcd] = outp->dp.rate[i].rate * 10 / 200;
94 
95 	return nvkm_gsp_rm_ctrl_wr(&disp->rm.objcom, ctrl);
96 }
97 
98 static int
r570_dp_get_caps(struct nvkm_disp * disp,int * plink_bw,bool * pmst,bool * pwm)99 r570_dp_get_caps(struct nvkm_disp *disp, int *plink_bw, bool *pmst, bool *pwm)
100 {
101 	NV0073_CTRL_CMD_DP_GET_CAPS_PARAMS *ctrl;
102 	int ret;
103 
104 	ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom,
105 				    NV0073_CTRL_CMD_DP_GET_CAPS, sizeof(*ctrl));
106 	if (IS_ERR(ctrl))
107 		return PTR_ERR(ctrl);
108 
109 	ctrl->sorIndex = ~0;
110 
111 	ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
112 	if (ret) {
113 		nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
114 		return ret;
115 	}
116 
117 	switch (NVVAL_GET(ctrl->maxLinkRate, NV0073_CTRL_CMD, DP_GET_CAPS, MAX_LINK_RATE)) {
118 	case NV0073_CTRL_CMD_DP_GET_CAPS_MAX_LINK_RATE_1_62:
119 		*plink_bw = 0x06;
120 		break;
121 	case NV0073_CTRL_CMD_DP_GET_CAPS_MAX_LINK_RATE_2_70:
122 		*plink_bw = 0x0a;
123 		break;
124 	case NV0073_CTRL_CMD_DP_GET_CAPS_MAX_LINK_RATE_5_40:
125 		*plink_bw = 0x14;
126 		break;
127 	case NV0073_CTRL_CMD_DP_GET_CAPS_MAX_LINK_RATE_8_10:
128 		*plink_bw = 0x1e;
129 		break;
130 	default:
131 		*plink_bw = 0x00;
132 		break;
133 	}
134 
135 	*pmst = ctrl->bIsMultistreamSupported;
136 	*pwm = ctrl->bHasIncreasedWatermarkLimits;
137 	nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
138 	return 0;
139 }
140 
141 static int
r570_bl_ctrl(struct nvkm_disp * disp,unsigned display_id,bool set,int * pval)142 r570_bl_ctrl(struct nvkm_disp *disp, unsigned display_id, bool set, int *pval)
143 {
144 	u32 cmd = set ? NV0073_CTRL_CMD_SPECIFIC_SET_BACKLIGHT_BRIGHTNESS :
145 			NV0073_CTRL_CMD_SPECIFIC_GET_BACKLIGHT_BRIGHTNESS;
146 	NV0073_CTRL_SPECIFIC_BACKLIGHT_BRIGHTNESS_PARAMS *ctrl;
147 	int ret;
148 
149 	ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom, cmd, sizeof(*ctrl));
150 	if (IS_ERR(ctrl))
151 		return PTR_ERR(ctrl);
152 
153 	ctrl->displayId = BIT(display_id);
154 	ctrl->brightness = *pval;
155 	ctrl->brightnessType = NV0073_CTRL_SPECIFIC_BACKLIGHT_BRIGHTNESS_TYPE_PERCENT100;
156 
157 	ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
158 	if (ret)
159 		return ret;
160 
161 	*pval = ctrl->brightness;
162 
163 	nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
164 	return 0;
165 }
166 
167 static int
r570_disp_get_active(struct nvkm_disp * disp,unsigned head,u32 * displayid)168 r570_disp_get_active(struct nvkm_disp *disp, unsigned head, u32 *displayid)
169 {
170 	NV0073_CTRL_SYSTEM_GET_ACTIVE_PARAMS *ctrl;
171 	int ret;
172 
173 	ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom,
174 				    NV0073_CTRL_CMD_SYSTEM_GET_ACTIVE, sizeof(*ctrl));
175 	if (IS_ERR(ctrl))
176 		return PTR_ERR(ctrl);
177 
178 	ctrl->subDeviceInstance = 0;
179 	ctrl->head = head;
180 
181 	ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
182 	if (ret) {
183 		nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
184 		return ret;
185 	}
186 
187 	*displayid = ctrl->displayId;
188 	nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
189 	return 0;
190 }
191 static int
r570_disp_get_connect_state(struct nvkm_disp * disp,unsigned display_id)192 r570_disp_get_connect_state(struct nvkm_disp *disp, unsigned display_id)
193 {
194 	NV0073_CTRL_SYSTEM_GET_CONNECT_STATE_PARAMS *ctrl;
195 	int ret;
196 
197 	ctrl = nvkm_gsp_rm_ctrl_get(&disp->rm.objcom,
198 				    NV0073_CTRL_CMD_SYSTEM_GET_CONNECT_STATE, sizeof(*ctrl));
199 	if (IS_ERR(ctrl))
200 		return PTR_ERR(ctrl);
201 
202 	ctrl->subDeviceInstance = 0;
203 	ctrl->displayMask = BIT(display_id);
204 
205 	ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
206 	if (ret == 0 && (ctrl->displayMask & BIT(display_id)))
207 		ret = 1;
208 
209 	nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
210 	return ret;
211 }
212 
213 static int
r570_disp_get_supported(struct nvkm_disp * disp,unsigned long * pmask)214 r570_disp_get_supported(struct nvkm_disp *disp, unsigned long *pmask)
215 {
216 	NV0073_CTRL_SYSTEM_GET_SUPPORTED_PARAMS *ctrl;
217 
218 	ctrl = nvkm_gsp_rm_ctrl_rd(&disp->rm.objcom,
219 				   NV0073_CTRL_CMD_SYSTEM_GET_SUPPORTED, sizeof(*ctrl));
220 	if (IS_ERR(ctrl))
221 		return PTR_ERR(ctrl);
222 
223 	*pmask = ctrl->displayMask;
224 
225 	nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
226 	return 0;
227 }
228 
229 static int
r570_disp_get_static_info(struct nvkm_disp * disp)230 r570_disp_get_static_info(struct nvkm_disp *disp)
231 {
232 	NV2080_CTRL_INTERNAL_DISPLAY_GET_STATIC_INFO_PARAMS *ctrl;
233 	struct nvkm_gsp *gsp = disp->engine.subdev.device->gsp;
234 
235 	ctrl = nvkm_gsp_rm_ctrl_rd(&gsp->internal.device.subdevice,
236 				   NV2080_CTRL_CMD_INTERNAL_DISPLAY_GET_STATIC_INFO,
237 				   sizeof(*ctrl));
238 	if (IS_ERR(ctrl))
239 		return PTR_ERR(ctrl);
240 
241 	disp->wndw.mask = ctrl->windowPresentMask;
242 	disp->wndw.nr = fls(disp->wndw.mask);
243 
244 	nvkm_gsp_rm_ctrl_done(&gsp->internal.device.subdevice, ctrl);
245 	return 0;
246 }
247 
248 const struct nvkm_rm_api_disp
249 r570_disp = {
250 	.get_static_info = r570_disp_get_static_info,
251 	.get_supported = r570_disp_get_supported,
252 	.get_connect_state = r570_disp_get_connect_state,
253 	.get_active = r570_disp_get_active,
254 	.bl_ctrl = r570_bl_ctrl,
255 	.dp = {
256 		.get_caps = r570_dp_get_caps,
257 		.set_indexed_link_rates = r570_dp_set_indexed_link_rates,
258 	},
259 	.chan = {
260 		.set_pushbuf = r570_disp_chan_set_pushbuf,
261 		.dmac_alloc = r570_dmac_alloc,
262 	},
263 };
264