Merge tag 'for-6.9/dm-vdo' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / nvif / outp.c
1 /*
2  * Copyright 2021 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  */
22 #include <nvif/outp.h>
23 #include <nvif/disp.h>
24 #include <nvif/printf.h>
25
26 #include <nvif/class.h>
27
28 int
29 nvif_outp_dp_mst_vcpi(struct nvif_outp *outp, int head,
30                       u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn)
31 {
32         struct nvif_outp_dp_mst_vcpi_v0 args;
33         int ret;
34
35         args.version = 0;
36         args.head = head;
37         args.start_slot = start_slot;
38         args.num_slots = num_slots;
39         args.pbn = pbn;
40         args.aligned_pbn = aligned_pbn;
41
42         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_MST_VCPI, &args, sizeof(args));
43         NVIF_ERRON(ret, &outp->object,
44                    "[DP_MST_VCPI head:%d start_slot:%02x num_slots:%02x pbn:%04x aligned_pbn:%04x]",
45                    args.head, args.start_slot, args.num_slots, args.pbn, args.aligned_pbn);
46         return ret;
47 }
48
49 int
50 nvif_outp_dp_mst_id_put(struct nvif_outp *outp, u32 id)
51 {
52         struct nvif_outp_dp_mst_id_get_v0 args;
53         int ret;
54
55         args.version = 0;
56         args.id = id;
57         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_MST_ID_PUT, &args, sizeof(args));
58         NVIF_ERRON(ret, &outp->object, "[DP_MST_ID_PUT id:%08x]", args.id);
59         return ret;
60 }
61
62 int
63 nvif_outp_dp_mst_id_get(struct nvif_outp *outp, u32 *id)
64 {
65         struct nvif_outp_dp_mst_id_get_v0 args;
66         int ret;
67
68         args.version = 0;
69         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_MST_ID_GET, &args, sizeof(args));
70         NVIF_ERRON(ret, &outp->object, "[DP_MST_ID_GET] id:%08x", args.id);
71         if (ret)
72                 return ret;
73
74         *id = args.id;
75         return 0;
76 }
77
78 int
79 nvif_outp_dp_sst(struct nvif_outp *outp, int head, u32 watermark, u32 hblanksym, u32 vblanksym)
80 {
81         struct nvif_outp_dp_sst_v0 args;
82         int ret;
83
84         args.version = 0;
85         args.head = head;
86         args.watermark = watermark;
87         args.hblanksym = hblanksym;
88         args.vblanksym = vblanksym;
89         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_SST, &args, sizeof(args));
90         NVIF_ERRON(ret, &outp->object,
91                    "[DP_SST head:%d watermark:%d hblanksym:%d vblanksym:%d]",
92                    args.head, args.watermark, args.hblanksym, args.vblanksym);
93         return ret;
94 }
95
96 int
97 nvif_outp_dp_drive(struct nvif_outp *outp, u8 link_nr, u8 pe[4], u8 vs[4])
98 {
99         struct nvif_outp_dp_drive_v0 args;
100         int ret;
101
102         args.version = 0;
103         args.lanes   = link_nr;
104         memcpy(args.pe, pe, sizeof(args.pe));
105         memcpy(args.vs, vs, sizeof(args.vs));
106
107         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_DRIVE, &args, sizeof(args));
108         NVIF_ERRON(ret, &outp->object, "[DP_DRIVE lanes:%d]", args.lanes);
109         return ret;
110 }
111
112 int
113 nvif_outp_dp_train(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE], u8 lttprs,
114                    u8 link_nr, u32 link_bw, bool mst, bool post_lt_adj, bool retrain)
115 {
116         struct nvif_outp_dp_train_v0 args;
117         int ret;
118
119         args.version = 0;
120         args.retrain = retrain;
121         args.mst = mst;
122         args.lttprs = lttprs;
123         args.post_lt_adj = post_lt_adj;
124         args.link_nr = link_nr;
125         args.link_bw = link_bw;
126         memcpy(args.dpcd, dpcd, sizeof(args.dpcd));
127
128         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_TRAIN, &args, sizeof(args));
129         NVIF_ERRON(ret, &outp->object,
130                    "[DP_TRAIN retrain:%d mst:%d lttprs:%d post_lt_adj:%d nr:%d bw:%d]",
131                    args.retrain, args.mst, args.lttprs, args.post_lt_adj, args.link_nr,
132                    args.link_bw);
133         return ret;
134 }
135
136 int
137 nvif_outp_dp_rates(struct nvif_outp *outp, struct nvif_outp_dp_rate *rate, int rate_nr)
138 {
139         struct nvif_outp_dp_rates_v0 args;
140         int ret;
141
142         if (rate_nr > ARRAY_SIZE(args.rate))
143                 return -EINVAL;
144
145         args.version = 0;
146         args.rates = rate_nr;
147         for (int i = 0; i < args.rates; i++, rate++) {
148                 args.rate[i].dpcd = rate->dpcd;
149                 args.rate[i].rate = rate->rate;
150         }
151
152         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_RATES, &args, sizeof(args));
153         NVIF_ERRON(ret, &outp->object, "[DP_RATES rates:%d]", args.rates);
154         return ret;
155 }
156
157 int
158 nvif_outp_dp_aux_xfer(struct nvif_outp *outp, u8 type, u8 *psize, u32 addr, u8 *data)
159 {
160         struct nvif_outp_dp_aux_xfer_v0 args;
161         u8 size = *psize;
162         int ret;
163
164         args.version = 0;
165         args.type = type;
166         args.size = size;
167         args.addr = addr;
168         memcpy(args.data, data, size);
169         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_AUX_XFER, &args, sizeof(args));
170         NVIF_DEBUG(&outp->object, "[DP_AUX_XFER type:%d size:%d addr:%05x] %d size:%d (ret: %d)",
171                    args.type, size, args.addr, ret, args.size, ret);
172         if (ret < 0)
173                 return ret;
174
175         *psize = args.size;
176
177         memcpy(data, args.data, size);
178         return ret;
179 }
180
181 int
182 nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable)
183 {
184         struct nvif_outp_dp_aux_pwr_v0 args;
185         int ret;
186
187         args.version = 0;
188         args.state = enable;
189
190         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_AUX_PWR, &args, sizeof(args));
191         NVIF_ERRON(ret, &outp->object, "[DP_AUX_PWR state:%d]", args.state);
192         return ret;
193 }
194
195 int
196 nvif_outp_hda_eld(struct nvif_outp *outp, int head, void *data, u32 size)
197 {
198         struct {
199                 struct nvif_outp_hda_eld_v0 mthd;
200                 u8 data[128];
201         } args;
202         int ret;
203
204         if (WARN_ON(size > ARRAY_SIZE(args.data)))
205                 return -EINVAL;
206
207         args.mthd.version = 0;
208         args.mthd.head = head;
209
210         memcpy(args.data, data, size);
211         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDA_ELD, &args, sizeof(args.mthd) + size);
212         NVIF_ERRON(ret, &outp->object, "[HDA_ELD head:%d size:%d]", head, size);
213         return ret;
214 }
215
216 int
217 nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_v0 *args, u32 size)
218 {
219         int ret;
220
221         args->type = type;
222
223         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_INFOFRAME, args, sizeof(*args) + size);
224         NVIF_ERRON(ret, &outp->object, "[INFOFRAME type:%d size:%d]", type, size);
225         return ret;
226 }
227
228 int
229 nvif_outp_hdmi(struct nvif_outp *outp, int head, bool enable, u8 max_ac_packet, u8 rekey,
230                u32 khz, bool scdc, bool scdc_scrambling, bool scdc_low_rates)
231 {
232         struct nvif_outp_hdmi_v0 args;
233         int ret;
234
235         args.version = 0;
236         args.head = head;
237         args.enable = enable;
238         args.max_ac_packet = max_ac_packet;
239         args.rekey = rekey;
240         args.khz = khz;
241         args.scdc = scdc;
242         args.scdc_scrambling = scdc_scrambling;
243         args.scdc_low_rates = scdc_low_rates;
244
245         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDMI, &args, sizeof(args));
246         NVIF_ERRON(ret, &outp->object,
247                    "[HDMI head:%d enable:%d max_ac_packet:%d rekey:%d khz:%d scdc:%d "
248                    "scdc_scrambling:%d scdc_low_rates:%d]",
249                    args.head, args.enable, args.max_ac_packet, args.rekey, args.khz,
250                    args.scdc, args.scdc_scrambling, args.scdc_low_rates);
251         return ret;
252 }
253
254 int
255 nvif_outp_lvds(struct nvif_outp *outp, bool dual, bool bpc8)
256 {
257         struct nvif_outp_lvds_v0 args;
258         int ret;
259
260         args.version = 0;
261         args.dual = dual;
262         args.bpc8 = bpc8;
263
264         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_LVDS, &args, sizeof(args));
265         NVIF_ERRON(ret, &outp->object, "[LVDS dual:%d 8bpc:%d]", args.dual, args.bpc8);
266         return ret;
267 }
268
269 int
270 nvif_outp_bl_set(struct nvif_outp *outp, int level)
271 {
272         struct nvif_outp_bl_set_v0 args;
273         int ret;
274
275         args.version = 0;
276         args.level = level;
277
278         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_BL_SET, &args, sizeof(args));
279         NVIF_ERRON(ret, &outp->object, "[BL_SET level:%d]", args.level);
280         return ret;
281 }
282
283 int
284 nvif_outp_bl_get(struct nvif_outp *outp)
285 {
286         struct nvif_outp_bl_get_v0 args;
287         int ret;
288
289         args.version = 0;
290
291         ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_BL_GET, &args, sizeof(args));
292         NVIF_ERRON(ret, &outp->object, "[BL_GET level:%d]", args.level);
293         return ret ? ret : args.level;
294 }
295
296 void
297 nvif_outp_release(struct nvif_outp *outp)
298 {
299         int ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_RELEASE, NULL, 0);
300         NVIF_ERRON(ret, &outp->object, "[RELEASE]");
301         outp->or.id = -1;
302 }
303
304 static inline int
305 nvif_outp_acquire(struct nvif_outp *outp, u8 type, struct nvif_outp_acquire_v0 *args)
306 {
307         int ret;
308
309         args->version = 0;
310         args->type = type;
311
312         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_ACQUIRE, args, sizeof(*args));
313         if (ret)
314                 return ret;
315
316         outp->or.id = args->or;
317         outp->or.link = args->link;
318         return 0;
319 }
320
321 int
322 nvif_outp_acquire_pior(struct nvif_outp *outp)
323 {
324         struct nvif_outp_acquire_v0 args;
325         int ret;
326
327         ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_PIOR, &args);
328         NVIF_ERRON(ret, &outp->object, "[ACQUIRE PIOR] or:%d", args.or);
329         return ret;
330 }
331
332 int
333 nvif_outp_acquire_sor(struct nvif_outp *outp, bool hda)
334 {
335         struct nvif_outp_acquire_v0 args;
336         int ret;
337
338         args.sor.hda = hda;
339
340         ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_SOR, &args);
341         NVIF_ERRON(ret, &outp->object, "[ACQUIRE SOR] or:%d link:%d", args.or, args.link);
342         return ret;
343 }
344
345 int
346 nvif_outp_acquire_dac(struct nvif_outp *outp)
347 {
348         struct nvif_outp_acquire_v0 args;
349         int ret;
350
351         ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DAC, &args);
352         NVIF_ERRON(ret, &outp->object, "[ACQUIRE DAC] or:%d", args.or);
353         return ret;
354 }
355
356 static int
357 nvif_outp_inherit(struct nvif_outp *outp,
358                   u8 proto,
359                   struct nvif_outp_inherit_v0 *args,
360                   u8 *proto_out)
361 {
362         int ret;
363
364         args->version = 0;
365         args->proto = proto;
366
367         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_INHERIT, args, sizeof(*args));
368         if (ret)
369                 return ret;
370
371         outp->or.id = args->or;
372         outp->or.link = args->link;
373         *proto_out = args->proto;
374         return 0;
375 }
376
377 int
378 nvif_outp_inherit_lvds(struct nvif_outp *outp, u8 *proto_out)
379 {
380         struct nvif_outp_inherit_v0 args;
381         int ret;
382
383         ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_LVDS, &args, proto_out);
384         NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:LVDS] ret:%d", ret);
385         return ret ?: args.head;
386 }
387
388 int
389 nvif_outp_inherit_tmds(struct nvif_outp *outp, u8 *proto_out)
390 {
391         struct nvif_outp_inherit_v0 args;
392         int ret;
393
394         ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_TMDS, &args, proto_out);
395         NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:TMDS] ret:%d", ret);
396         return ret ?: args.head;
397 }
398
399 int
400 nvif_outp_inherit_dp(struct nvif_outp *outp, u8 *proto_out)
401 {
402         struct nvif_outp_inherit_v0 args;
403         int ret;
404
405         ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_DP, &args, proto_out);
406         NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:DP] ret:%d", ret);
407
408         // TODO: Get current link info
409
410         return ret ?: args.head;
411 }
412
413 int
414 nvif_outp_inherit_rgb_crt(struct nvif_outp *outp, u8 *proto_out)
415 {
416         struct nvif_outp_inherit_v0 args;
417         int ret;
418
419         ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_RGB_CRT, &args, proto_out);
420         NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:RGB_CRT] ret:%d", ret);
421         return ret ?: args.head;
422 }
423
424 int
425 nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval)
426 {
427         struct nvif_outp_load_detect_v0 args;
428         int ret;
429
430         args.version = 0;
431         args.data = loadval;
432
433         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_LOAD_DETECT, &args, sizeof(args));
434         NVIF_ERRON(ret, &outp->object, "[LOAD_DETECT data:%08x] load:%02x", args.data, args.load);
435         return ret < 0 ? ret : args.load;
436 }
437
438 int
439 nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid)
440 {
441         struct nvif_outp_edid_get_v0 *args;
442         int ret;
443
444         args = kmalloc(sizeof(*args), GFP_KERNEL);
445         if (!args)
446                 return -ENOMEM;
447
448         args->version = 0;
449
450         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_EDID_GET, args, sizeof(*args));
451         NVIF_ERRON(ret, &outp->object, "[EDID_GET] size:%d", args->size);
452         if (ret)
453                 goto done;
454
455         *pedid = kmalloc(args->size, GFP_KERNEL);
456         if (!*pedid) {
457                 ret = -ENOMEM;
458                 goto done;
459         }
460
461         memcpy(*pedid, args->data, args->size);
462         ret = args->size;
463 done:
464         kfree(args);
465         return ret;
466 }
467
468 enum nvif_outp_detect_status
469 nvif_outp_detect(struct nvif_outp *outp)
470 {
471         struct nvif_outp_detect_v0 args;
472         int ret;
473
474         args.version = 0;
475
476         ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_DETECT, &args, sizeof(args));
477         NVIF_ERRON(ret, &outp->object, "[DETECT] status:%02x", args.status);
478         if (ret)
479                 return UNKNOWN;
480
481         switch (args.status) {
482         case NVIF_OUTP_DETECT_V0_NOT_PRESENT: return NOT_PRESENT;
483         case NVIF_OUTP_DETECT_V0_PRESENT: return PRESENT;
484         case NVIF_OUTP_DETECT_V0_UNKNOWN: return UNKNOWN;
485         default:
486                 WARN_ON(1);
487                 break;
488         }
489
490         return UNKNOWN;
491 }
492
493 void
494 nvif_outp_dtor(struct nvif_outp *outp)
495 {
496         nvif_object_dtor(&outp->object);
497 }
498
499 int
500 nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_outp *outp)
501 {
502         struct nvif_outp_v0 args;
503         int ret;
504
505         args.version = 0;
506         args.id = id;
507
508         ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP,
509                                &args, sizeof(args), &outp->object);
510         NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id);
511         if (ret)
512                 return ret;
513
514         outp->id = args.id;
515
516         switch (args.type) {
517         case NVIF_OUTP_V0_TYPE_DAC : outp->info.type = NVIF_OUTP_DAC; break;
518         case NVIF_OUTP_V0_TYPE_SOR : outp->info.type = NVIF_OUTP_SOR; break;
519         case NVIF_OUTP_V0_TYPE_PIOR: outp->info.type = NVIF_OUTP_PIOR; break;
520                 break;
521         default:
522                 WARN_ON(1);
523                 nvif_outp_dtor(outp);
524                 return -EINVAL;
525         }
526
527         switch (args.proto) {
528         case NVIF_OUTP_V0_PROTO_RGB_CRT:
529                 outp->info.proto = NVIF_OUTP_RGB_CRT;
530                 outp->info.rgb_crt.freq_max = args.rgb_crt.freq_max;
531                 break;
532         case NVIF_OUTP_V0_PROTO_TMDS:
533                 outp->info.proto = NVIF_OUTP_TMDS;
534                 outp->info.tmds.dual = args.tmds.dual;
535                 break;
536         case NVIF_OUTP_V0_PROTO_LVDS:
537                 outp->info.proto = NVIF_OUTP_LVDS;
538                 outp->info.lvds.acpi_edid = args.lvds.acpi_edid;
539                 break;
540         case NVIF_OUTP_V0_PROTO_DP:
541                 outp->info.proto = NVIF_OUTP_DP;
542                 outp->info.dp.aux = args.dp.aux;
543                 outp->info.dp.mst = args.dp.mst;
544                 outp->info.dp.increased_wm = args.dp.increased_wm;
545                 outp->info.dp.link_nr = args.dp.link_nr;
546                 outp->info.dp.link_bw = args.dp.link_bw;
547                 break;
548         default:
549                 WARN_ON(1);
550                 nvif_outp_dtor(outp);
551                 return -EINVAL;
552         }
553
554         outp->info.heads = args.heads;
555         outp->info.ddc = args.ddc;
556         outp->info.conn = args.conn;
557
558         outp->or.id = -1;
559         return 0;
560 }