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(&params, 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                     &params,
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                                                       &params, 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(&params, 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                     &params,
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                                                      &params,
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