1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * File: nvhdmipkt_0073.c
24 *
25 * Purpose: Provides infoframe write functions for HDMI library for Pre-KEPLER chips
26 */
27
28 #include "nvhdmipkt_common.h"
29 #include "nvhdmipkt_class.h"
30
31 #include "nvhdmipkt_internal.h"
32
33 #include "hdmi_spec.h"
34 #include "ctrl/ctrl0073/ctrl0073specific.h"
35
36 NVHDMIPKT_RESULT
37 hdmiPacketCtrl0073(NVHDMIPKT_CLASS* pThis,
38 NvU32 subDevice,
39 NvU32 displayId,
40 NvU32 head,
41 NVHDMIPKT_TYPE packetType,
42 NVHDMIPKT_TC transmitControl);
43
44 NVHDMIPKT_RESULT
45 hdmiPacketWrite0073(NVHDMIPKT_CLASS* pThis,
46 NvU32 subDevice,
47 NvU32 displayId,
48 NvU32 head,
49 NVHDMIPKT_TYPE packetType,
50 NVHDMIPKT_TC transmitControl,
51 NvU32 packetLen,
52 NvU8 const *const pPacket);
53
54 /*
55 * hdmiPacketCtrl0073
56 */
57 NVHDMIPKT_RESULT
hdmiPacketCtrl0073(NVHDMIPKT_CLASS * pThis,NvU32 subDevice,NvU32 displayId,NvU32 head,NVHDMIPKT_TYPE packetType,NVHDMIPKT_TC transmitControl)58 hdmiPacketCtrl0073(NVHDMIPKT_CLASS* pThis,
59 NvU32 subDevice,
60 NvU32 displayId,
61 NvU32 head,
62 NVHDMIPKT_TYPE packetType,
63 NVHDMIPKT_TC transmitControl)
64 {
65 NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
66 NV0073_CTRL_SPECIFIC_SET_OD_PACKET_CTRL_PARAMS params = {0};
67
68 NVMISC_MEMSET(¶ms, 0, sizeof(params));
69
70 params.subDeviceInstance = subDevice;
71 params.displayId = displayId;
72 params.type = pThis->translatePacketType(pThis, packetType);
73 params.transmitControl = pThis->translateTransmitControl(pThis, transmitControl);
74
75 #if NVHDMIPKT_RM_CALLS_INTERNAL
76 if (NvRmControl(pThis->clientHandles.hClient,
77 pThis->clientHandles.hDisplay,
78 NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET_CTRL,
79 ¶ms,
80 sizeof(params)) != NVOS_STATUS_SUCCESS)
81
82 #else // !NVHDMIPKT_RM_CALLS_INTERNAL
83 NvBool bSuccess = pThis->callback.rmDispControl2(pThis->cbHandle,
84 params.subDeviceInstance,
85 NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET_CTRL,
86 ¶ms, sizeof(params));
87 if (bSuccess == NV_FALSE)
88 #endif // NVHDMIPKT_RM_CALLS_INTERNAL
89 {
90 NvHdmiPkt_Print(pThis, "ERROR - RM call to hdmiPacketCtrl failed.");
91 NvHdmiPkt_Assert(0);
92 result = NVHDMIPKT_FAIL;
93 }
94
95 return result;
96 }
97
98 /*
99 * hdmiPacketWrite0073
100 */
101 NVHDMIPKT_RESULT
hdmiPacketWrite0073(NVHDMIPKT_CLASS * pThis,NvU32 subDevice,NvU32 displayId,NvU32 head,NVHDMIPKT_TYPE packetType,NVHDMIPKT_TC transmitControl,NvU32 packetLen,NvU8 const * const pPacket)102 hdmiPacketWrite0073(NVHDMIPKT_CLASS* pThis,
103 NvU32 subDevice,
104 NvU32 displayId,
105 NvU32 head,
106 NVHDMIPKT_TYPE packetType,
107 NVHDMIPKT_TC transmitControl,
108 NvU32 packetLen,
109 NvU8 const *const pPacket)
110 {
111 NVHDMIPKT_RESULT result = NVHDMIPKT_SUCCESS;
112
113 if (packetLen > NV0073_CTRL_SET_OD_MAX_PACKET_SIZE)
114 {
115 return NVHDMIPKT_INVALID_ARG;
116 }
117
118 NV0073_CTRL_SPECIFIC_SET_OD_PACKET_PARAMS params = {0};
119
120 NVMISC_MEMSET(¶ms, 0, sizeof(params));
121
122 params.subDeviceInstance = subDevice;
123 params.displayId = displayId;
124 params.packetSize = packetLen;
125 params.transmitControl = pThis->translateTransmitControl(pThis, transmitControl);
126
127 // init the infoframe packet
128 NVMISC_MEMSET(params.aPacket, 0, NV0073_CTRL_SET_OD_MAX_PACKET_SIZE);
129
130 // copy the payload
131 NVMISC_MEMCPY(params.aPacket, pPacket, packetLen);
132
133 #if NVHDMIPKT_RM_CALLS_INTERNAL
134 if (NvRmControl(pThis->clientHandles.hClient,
135 pThis->clientHandles.hDisplay,
136 NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET,
137 ¶ms,
138 sizeof(params)) != NVOS_STATUS_SUCCESS)
139
140 #else // !NVHDMIPKT_RM_CALLS_INTERNAL
141 NvBool bSuccess = pThis->callback.rmDispControl2(pThis->cbHandle,
142 params.subDeviceInstance,
143 NV0073_CTRL_CMD_SPECIFIC_SET_OD_PACKET,
144 ¶ms,
145 sizeof(params));
146 if (bSuccess == NV_FALSE)
147 #endif // NVHDMIPKT_RM_CALLS_INTERNAL
148 {
149 NvHdmiPkt_Print(pThis, "ERROR - RM call to hdmiPacketWrite failed.");
150 NvHdmiPkt_Assert(0);
151 result = NVHDMIPKT_FAIL;
152 }
153
154 return result;
155 }
156
157 /*
158 * translatePacketType0073
159 */
160 static NvU32
translatePacketType0073(NVHDMIPKT_CLASS * pThis,NVHDMIPKT_TYPE packetType)161 translatePacketType0073(NVHDMIPKT_CLASS* pThis,
162 NVHDMIPKT_TYPE packetType)
163 {
164 NvU32 type0073 = 0;
165
166 switch (packetType)
167 {
168 case NVHDMIPKT_TYPE_AVI_INFOFRAME:
169 type0073 = pktType_AviInfoFrame;
170 break;
171
172 case NVHDMIPKT_TYPE_GENERIC:
173 type0073 = pktType_GamutMetadata;
174 break;
175
176 case NVHDMIPKT_TYPE_GENERAL_CONTROL:
177 type0073 = pktType_GeneralControl;
178 break;
179
180 case NVHDMIPKT_TYPE_VENDOR_SPECIFIC_INFOFRAME:
181 type0073 = pktType_VendorSpecInfoFrame;
182 break;
183
184 case NVHDMIPKT_TYPE_AUDIO_INFOFRAME:
185 type0073 = pktType_AudioInfoFrame;
186 break;
187
188 default:
189 NvHdmiPkt_Print(pThis, "ERROR - translatePacketType wrong packet type: %0x",
190 packetType);
191 NvHdmiPkt_Assert(0);
192 break;
193 }
194
195 return type0073;
196 }
197
198 /*
199 * translateTransmitControl0073
200 */
201 static NvU32
translateTransmitControl0073(NVHDMIPKT_CLASS * pThis,NVHDMIPKT_TC transmitControl)202 translateTransmitControl0073(NVHDMIPKT_CLASS* pThis,
203 NVHDMIPKT_TC transmitControl)
204 {
205 NvU32 tc = 0;
206
207 // TODO: tc validation
208 if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _ENABLE, _EN, transmitControl))
209 {
210 tc = FLD_SET_DRF(0073, _CTRL_SPECIFIC_SET_OD_PACKET_CTRL_TRANSMIT_CONTROL,
211 _ENABLE, _YES, tc);
212 }
213
214 if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _OTHER, _EN, transmitControl))
215 {
216 tc = FLD_SET_DRF(0073, _CTRL_SPECIFIC_SET_OD_PACKET_CTRL_TRANSMIT_CONTROL,
217 _OTHER_FRAME, _ENABLE, tc);
218 }
219
220 if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _SINGLE, _EN, transmitControl))
221 {
222 tc = FLD_SET_DRF(0073, _CTRL_SPECIFIC_SET_OD_PACKET_CTRL_TRANSMIT_CONTROL,
223 _SINGLE_FRAME, _ENABLE, tc);
224 }
225
226 if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _HBLANK, _EN, transmitControl))
227 {
228 tc = FLD_SET_DRF(0073, _CTRL_SPECIFIC_SET_OD_PACKET_CTRL_TRANSMIT_CONTROL,
229 _ON_HBLANK, _ENABLE, tc);
230 }
231
232 if (FLD_TEST_DRF(_HDMI_PKT, _TRANSMIT_CTRL, _VIDEO_FMT, _HW_CTRL, transmitControl))
233 {
234 tc = FLD_SET_DRF(0073, _CTRL_SPECIFIC_SET_OD_PACKET_CTRL_TRANSMIT_CONTROL,
235 _VIDEO_FMT, _HW_CONTROLLED, tc);
236 }
237
238 return tc;
239 }
240
241 // non-HW - class utility/maintenance functions
242 /*
243 * hdmiConstructor0073
244 */
245 NvBool
hdmiConstructor0073(NVHDMIPKT_CLASS * pThis)246 hdmiConstructor0073(NVHDMIPKT_CLASS* pThis)
247 {
248 return NV_TRUE;
249 }
250
251 /*
252 * hdmiUnDestructor0073
253 */
254 void
hdmiDestructor0073(NVHDMIPKT_CLASS * pThis)255 hdmiDestructor0073(NVHDMIPKT_CLASS* pThis)
256
257 {
258 return;
259 }
260
261 // Below are dummy functions for the HW functions not needed for a display class
262 /*
263 * hdmiWriteDummyPacket
264 */
265 void
hdmiWriteDummyPacket(NVHDMIPKT_CLASS * pThis,NvU32 * pBaseReg,NvU32 head,NvU32 packetLen,NvU8 const * const pPacket)266 hdmiWriteDummyPacket(NVHDMIPKT_CLASS* pThis,
267 NvU32* pBaseReg,
268 NvU32 head,
269 NvU32 packetLen,
270 NvU8 const *const pPacket)
271 {
272 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiWriteDummyPacket called. "
273 "Should never be called.");
274 NvHdmiPkt_Assert(0);
275 return;
276 }
277
278 /*
279 * hdmiReadDummyPacketStatus
280 */
281 static NvBool
hdmiReadDummyPacketStatus(NVHDMIPKT_CLASS * pThis,NvU32 * pBaseReg,NvU32 head,NvU32 pktType0073)282 hdmiReadDummyPacketStatus(NVHDMIPKT_CLASS* pThis,
283 NvU32* pBaseReg,
284 NvU32 head,
285 NvU32 pktType0073)
286 {
287 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiReadDummyPacketStatus called. "
288 "Should never be called.");
289 NvHdmiPkt_Assert(0);
290 return NV_TRUE;
291 }
292
293 /*
294 * hdmiWriteDummyPacketCtrl
295 */
296 static NVHDMIPKT_RESULT
hdmiWriteDummyPacketCtrl(NVHDMIPKT_CLASS * pThis,NvU32 * pBaseReg,NvU32 head,NvU32 pktType0073,NvU32 transmitControl,NvBool bDisable)297 hdmiWriteDummyPacketCtrl(NVHDMIPKT_CLASS* pThis,
298 NvU32* pBaseReg,
299 NvU32 head,
300 NvU32 pktType0073,
301 NvU32 transmitControl,
302 NvBool bDisable)
303 {
304 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiWriteDummyPacketCtrl called. "
305 "Should never be called.");
306 NvHdmiPkt_Assert(0);
307 return NVHDMIPKT_SUCCESS;
308 }
309
310 NVHDMIPKT_RESULT
hdmiAssessLinkCapabilitiesDummy(NVHDMIPKT_CLASS * pThis,NvU32 subDevice,NvU32 displayId,NVT_EDID_INFO const * const pSinkEdid,HDMI_SRC_CAPS * pSrcCaps,HDMI_SINK_CAPS * pSinkCaps)311 hdmiAssessLinkCapabilitiesDummy(NVHDMIPKT_CLASS *pThis,
312 NvU32 subDevice,
313 NvU32 displayId,
314 NVT_EDID_INFO const * const pSinkEdid,
315 HDMI_SRC_CAPS *pSrcCaps,
316 HDMI_SINK_CAPS *pSinkCaps)
317 {
318 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiAssessLinkCapabilitiesDummy called. "
319 "Should never be called.");
320 NvHdmiPkt_Assert(0);
321 return NVHDMIPKT_SUCCESS;
322 }
323
324 NVHDMIPKT_RESULT
hdmiQueryFRLConfigDummy(NVHDMIPKT_CLASS * pThis,HDMI_VIDEO_TRANSPORT_INFO const * const pVidTransInfo,HDMI_QUERY_FRL_CLIENT_CONTROL const * const pClientCtrl,HDMI_SRC_CAPS const * const pSrcCaps,HDMI_SINK_CAPS const * const pSinkCaps,HDMI_FRL_CONFIG * pFRLConfig)325 hdmiQueryFRLConfigDummy(NVHDMIPKT_CLASS *pThis,
326 HDMI_VIDEO_TRANSPORT_INFO const * const pVidTransInfo,
327 HDMI_QUERY_FRL_CLIENT_CONTROL const * const pClientCtrl,
328 HDMI_SRC_CAPS const * const pSrcCaps,
329 HDMI_SINK_CAPS const * const pSinkCaps,
330 HDMI_FRL_CONFIG *pFRLConfig)
331 {
332 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiQueryFRLConfigDummy called. "
333 "Should never be called.");
334 NvHdmiPkt_Assert(0);
335 return NVHDMIPKT_SUCCESS;
336 }
337
338 NVHDMIPKT_RESULT
hdmiSetFRLConfigDummy(NVHDMIPKT_CLASS * pThis,NvU32 subDevice,NvU32 displayId,NvBool bFakeLt,HDMI_FRL_CONFIG * pFRLConfig)339 hdmiSetFRLConfigDummy(NVHDMIPKT_CLASS *pThis,
340 NvU32 subDevice,
341 NvU32 displayId,
342 NvBool bFakeLt,
343 HDMI_FRL_CONFIG *pFRLConfig)
344 {
345 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiSetFRLConfigDummy called. "
346 "Should never be called.");
347 NvHdmiPkt_Assert(0);
348 return NVHDMIPKT_SUCCESS;
349 }
350
351 NVHDMIPKT_RESULT
hdmiClearFRLConfigDummy(NVHDMIPKT_CLASS * pThis,NvU32 subDevice,NvU32 displayId)352 hdmiClearFRLConfigDummy(NVHDMIPKT_CLASS *pThis,
353 NvU32 subDevice,
354 NvU32 displayId)
355 {
356 NvHdmiPkt_Print(pThis, "ERROR - Dummy function hdmiClearFRLConfigDummy called. "
357 "Should never be called.");
358 NvHdmiPkt_Assert(0);
359 return NVHDMIPKT_SUCCESS;
360 }
361
362 /*
363 * initializeHdmiPktInterface0073
364 */
365 void
initializeHdmiPktInterface0073(NVHDMIPKT_CLASS * pClass)366 initializeHdmiPktInterface0073(NVHDMIPKT_CLASS* pClass)
367 {
368 pClass->hdmiPacketCtrl = hdmiPacketCtrl0073;
369 pClass->hdmiPacketWrite = hdmiPacketWrite0073;
370 pClass->translatePacketType = translatePacketType0073;
371 pClass->translateTransmitControl = translateTransmitControl0073;
372
373 // Functions below are mapped to dummy functions, as not needed for HW before GK104
374 pClass->hdmiReadPacketStatus = hdmiReadDummyPacketStatus;
375 pClass->hdmiWritePacketCtrl = hdmiWriteDummyPacketCtrl;
376 pClass->hdmiWriteAviPacket = hdmiWriteDummyPacket;
377 pClass->hdmiWriteAudioPacket = hdmiWriteDummyPacket;
378 pClass->hdmiWriteGenericPacket = hdmiWriteDummyPacket;
379 pClass->hdmiWriteGeneralCtrlPacket = hdmiWriteDummyPacket;
380 pClass->hdmiWriteVendorPacket = hdmiWriteDummyPacket;
381
382 // Update SF_USER data
383 pClass->dispSfUserClassId = 0;
384 pClass->dispSfUserSize = 0;
385
386 // Functions below are used by HDMI FRL and will be available for Ampere+.
387 pClass->hdmiAssessLinkCapabilities = hdmiAssessLinkCapabilitiesDummy;
388 pClass->hdmiQueryFRLConfig = hdmiQueryFRLConfigDummy;
389 pClass->hdmiSetFRLConfig = hdmiSetFRLConfigDummy;
390 pClass->hdmiClearFRLConfig = hdmiClearFRLConfigDummy;
391
392 }
393