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 DEFINE_RAW_FLEX(struct nvif_outp_hda_eld_v0, mthd, data, 128); 199 int ret; 200 201 if (WARN_ON(size > __member_size(mthd->data))) 202 return -EINVAL; 203 204 mthd->version = 0; 205 mthd->head = head; 206 207 memcpy(mthd->data, data, size); 208 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDA_ELD, mthd, sizeof(*mthd) + size); 209 NVIF_ERRON(ret, &outp->object, "[HDA_ELD head:%d size:%d]", head, size); 210 return ret; 211 } 212 213 int 214 nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_v0 *args, u32 size) 215 { 216 int ret; 217 218 args->type = type; 219 220 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_INFOFRAME, args, sizeof(*args) + size); 221 NVIF_ERRON(ret, &outp->object, "[INFOFRAME type:%d size:%d]", type, size); 222 return ret; 223 } 224 225 int 226 nvif_outp_hdmi(struct nvif_outp *outp, int head, bool enable, u8 max_ac_packet, u8 rekey, 227 u32 khz, bool scdc, bool scdc_scrambling, bool scdc_low_rates) 228 { 229 struct nvif_outp_hdmi_v0 args; 230 int ret; 231 232 args.version = 0; 233 args.head = head; 234 args.enable = enable; 235 args.max_ac_packet = max_ac_packet; 236 args.rekey = rekey; 237 args.khz = khz; 238 args.scdc = scdc; 239 args.scdc_scrambling = scdc_scrambling; 240 args.scdc_low_rates = scdc_low_rates; 241 242 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDMI, &args, sizeof(args)); 243 NVIF_ERRON(ret, &outp->object, 244 "[HDMI head:%d enable:%d max_ac_packet:%d rekey:%d khz:%d scdc:%d " 245 "scdc_scrambling:%d scdc_low_rates:%d]", 246 args.head, args.enable, args.max_ac_packet, args.rekey, args.khz, 247 args.scdc, args.scdc_scrambling, args.scdc_low_rates); 248 return ret; 249 } 250 251 int 252 nvif_outp_lvds(struct nvif_outp *outp, bool dual, bool bpc8) 253 { 254 struct nvif_outp_lvds_v0 args; 255 int ret; 256 257 args.version = 0; 258 args.dual = dual; 259 args.bpc8 = bpc8; 260 261 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_LVDS, &args, sizeof(args)); 262 NVIF_ERRON(ret, &outp->object, "[LVDS dual:%d 8bpc:%d]", args.dual, args.bpc8); 263 return ret; 264 } 265 266 int 267 nvif_outp_bl_set(struct nvif_outp *outp, int level) 268 { 269 struct nvif_outp_bl_set_v0 args; 270 int ret; 271 272 args.version = 0; 273 args.level = level; 274 275 ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_BL_SET, &args, sizeof(args)); 276 NVIF_ERRON(ret, &outp->object, "[BL_SET level:%d]", args.level); 277 return ret; 278 } 279 280 int 281 nvif_outp_bl_get(struct nvif_outp *outp) 282 { 283 struct nvif_outp_bl_get_v0 args; 284 int ret; 285 286 args.version = 0; 287 288 ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_BL_GET, &args, sizeof(args)); 289 NVIF_ERRON(ret, &outp->object, "[BL_GET level:%d]", args.level); 290 return ret ? ret : args.level; 291 } 292 293 void 294 nvif_outp_release(struct nvif_outp *outp) 295 { 296 int ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_RELEASE, NULL, 0); 297 NVIF_ERRON(ret, &outp->object, "[RELEASE]"); 298 outp->or.id = -1; 299 } 300 301 static inline int 302 nvif_outp_acquire(struct nvif_outp *outp, u8 type, struct nvif_outp_acquire_v0 *args) 303 { 304 int ret; 305 306 args->version = 0; 307 args->type = type; 308 309 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_ACQUIRE, args, sizeof(*args)); 310 if (ret) 311 return ret; 312 313 outp->or.id = args->or; 314 outp->or.link = args->link; 315 return 0; 316 } 317 318 int 319 nvif_outp_acquire_pior(struct nvif_outp *outp) 320 { 321 struct nvif_outp_acquire_v0 args; 322 int ret; 323 324 ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_PIOR, &args); 325 NVIF_ERRON(ret, &outp->object, "[ACQUIRE PIOR] or:%d", args.or); 326 return ret; 327 } 328 329 int 330 nvif_outp_acquire_sor(struct nvif_outp *outp, bool hda) 331 { 332 struct nvif_outp_acquire_v0 args; 333 int ret; 334 335 args.sor.hda = hda; 336 337 ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_SOR, &args); 338 NVIF_ERRON(ret, &outp->object, "[ACQUIRE SOR] or:%d link:%d", args.or, args.link); 339 return ret; 340 } 341 342 int 343 nvif_outp_acquire_dac(struct nvif_outp *outp) 344 { 345 struct nvif_outp_acquire_v0 args; 346 int ret; 347 348 ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DAC, &args); 349 NVIF_ERRON(ret, &outp->object, "[ACQUIRE DAC] or:%d", args.or); 350 return ret; 351 } 352 353 static int 354 nvif_outp_inherit(struct nvif_outp *outp, 355 u8 proto, 356 struct nvif_outp_inherit_v0 *args, 357 u8 *proto_out) 358 { 359 int ret; 360 361 args->version = 0; 362 args->proto = proto; 363 364 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_INHERIT, args, sizeof(*args)); 365 if (ret) 366 return ret; 367 368 outp->or.id = args->or; 369 outp->or.link = args->link; 370 *proto_out = args->proto; 371 return 0; 372 } 373 374 int 375 nvif_outp_inherit_lvds(struct nvif_outp *outp, u8 *proto_out) 376 { 377 struct nvif_outp_inherit_v0 args; 378 int ret; 379 380 ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_LVDS, &args, proto_out); 381 NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:LVDS] ret:%d", ret); 382 return ret ?: args.head; 383 } 384 385 int 386 nvif_outp_inherit_tmds(struct nvif_outp *outp, u8 *proto_out) 387 { 388 struct nvif_outp_inherit_v0 args; 389 int ret; 390 391 ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_TMDS, &args, proto_out); 392 NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:TMDS] ret:%d", ret); 393 return ret ?: args.head; 394 } 395 396 int 397 nvif_outp_inherit_dp(struct nvif_outp *outp, u8 *proto_out) 398 { 399 struct nvif_outp_inherit_v0 args; 400 int ret; 401 402 ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_DP, &args, proto_out); 403 NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:DP] ret:%d", ret); 404 405 // TODO: Get current link info 406 407 return ret ?: args.head; 408 } 409 410 int 411 nvif_outp_inherit_rgb_crt(struct nvif_outp *outp, u8 *proto_out) 412 { 413 struct nvif_outp_inherit_v0 args; 414 int ret; 415 416 ret = nvif_outp_inherit(outp, NVIF_OUTP_INHERIT_V0_RGB_CRT, &args, proto_out); 417 NVIF_ERRON(ret && ret != -ENODEV, &outp->object, "[INHERIT proto:RGB_CRT] ret:%d", ret); 418 return ret ?: args.head; 419 } 420 421 int 422 nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval) 423 { 424 struct nvif_outp_load_detect_v0 args; 425 int ret; 426 427 args.version = 0; 428 args.data = loadval; 429 430 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_LOAD_DETECT, &args, sizeof(args)); 431 NVIF_ERRON(ret, &outp->object, "[LOAD_DETECT data:%08x] load:%02x", args.data, args.load); 432 return ret < 0 ? ret : args.load; 433 } 434 435 int 436 nvif_outp_edid_get(struct nvif_outp *outp, u8 **pedid) 437 { 438 struct nvif_outp_edid_get_v0 *args; 439 int ret; 440 441 args = kmalloc(sizeof(*args), GFP_KERNEL); 442 if (!args) 443 return -ENOMEM; 444 445 args->version = 0; 446 447 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_EDID_GET, args, sizeof(*args)); 448 NVIF_ERRON(ret, &outp->object, "[EDID_GET] size:%d", args->size); 449 if (ret) 450 goto done; 451 452 *pedid = kmemdup(args->data, args->size, GFP_KERNEL); 453 if (!*pedid) { 454 ret = -ENOMEM; 455 goto done; 456 } 457 458 ret = args->size; 459 done: 460 kfree(args); 461 return ret; 462 } 463 464 enum nvif_outp_detect_status 465 nvif_outp_detect(struct nvif_outp *outp) 466 { 467 struct nvif_outp_detect_v0 args; 468 int ret; 469 470 args.version = 0; 471 472 ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_DETECT, &args, sizeof(args)); 473 NVIF_ERRON(ret, &outp->object, "[DETECT] status:%02x", args.status); 474 if (ret) 475 return UNKNOWN; 476 477 switch (args.status) { 478 case NVIF_OUTP_DETECT_V0_NOT_PRESENT: return NOT_PRESENT; 479 case NVIF_OUTP_DETECT_V0_PRESENT: return PRESENT; 480 case NVIF_OUTP_DETECT_V0_UNKNOWN: return UNKNOWN; 481 default: 482 WARN_ON(1); 483 break; 484 } 485 486 return UNKNOWN; 487 } 488 489 void 490 nvif_outp_dtor(struct nvif_outp *outp) 491 { 492 nvif_object_dtor(&outp->object); 493 } 494 495 int 496 nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_outp *outp) 497 { 498 struct nvif_outp_v0 args; 499 int ret; 500 501 args.version = 0; 502 args.id = id; 503 504 ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP, 505 &args, sizeof(args), &outp->object); 506 NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id); 507 if (ret) 508 return ret; 509 510 outp->id = args.id; 511 512 switch (args.type) { 513 case NVIF_OUTP_V0_TYPE_DAC : outp->info.type = NVIF_OUTP_DAC; break; 514 case NVIF_OUTP_V0_TYPE_SOR : outp->info.type = NVIF_OUTP_SOR; break; 515 case NVIF_OUTP_V0_TYPE_PIOR: outp->info.type = NVIF_OUTP_PIOR; break; 516 break; 517 default: 518 WARN_ON(1); 519 nvif_outp_dtor(outp); 520 return -EINVAL; 521 } 522 523 switch (args.proto) { 524 case NVIF_OUTP_V0_PROTO_RGB_CRT: 525 outp->info.proto = NVIF_OUTP_RGB_CRT; 526 outp->info.rgb_crt.freq_max = args.rgb_crt.freq_max; 527 break; 528 case NVIF_OUTP_V0_PROTO_TMDS: 529 outp->info.proto = NVIF_OUTP_TMDS; 530 outp->info.tmds.dual = args.tmds.dual; 531 break; 532 case NVIF_OUTP_V0_PROTO_LVDS: 533 outp->info.proto = NVIF_OUTP_LVDS; 534 outp->info.lvds.acpi_edid = args.lvds.acpi_edid; 535 break; 536 case NVIF_OUTP_V0_PROTO_DP: 537 outp->info.proto = NVIF_OUTP_DP; 538 outp->info.dp.aux = args.dp.aux; 539 outp->info.dp.mst = args.dp.mst; 540 outp->info.dp.increased_wm = args.dp.increased_wm; 541 outp->info.dp.link_nr = args.dp.link_nr; 542 outp->info.dp.link_bw = args.dp.link_bw; 543 break; 544 default: 545 WARN_ON(1); 546 nvif_outp_dtor(outp); 547 return -EINVAL; 548 } 549 550 outp->info.heads = args.heads; 551 outp->info.ddc = args.ddc; 552 outp->info.conn = args.conn; 553 554 outp->or.id = -1; 555 return 0; 556 } 557