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 } 561