17a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs/* 27a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * Copyright 2014 Red Hat Inc. 37a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * 47a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 57a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * copy of this software and associated documentation files (the "Software"), 67a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * to deal in the Software without restriction, including without limitation 77a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the 97a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * Software is furnished to do so, subject to the following conditions: 107a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * 117a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * The above copyright notice and this permission notice shall be included in 127a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * all copies or substantial portions of the Software. 137a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * 147a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 187a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 197a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 207a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE. 217a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * 227a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs * Authors: Ben Skeggs 237a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs */ 247a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 257a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs#include <subdev/i2c.h> 267a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs#include <subdev/bios.h> 277a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs#include <subdev/bios/conn.h> 287a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 297a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs#include "outp.h" 307a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 317a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsint 327a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs_nvkm_output_fini(struct nouveau_object *object, bool suspend) 337a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs{ 347a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nvkm_output *outp = (void *)object; 357a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs nv_ofuncs(outp->conn)->fini(nv_object(outp->conn), suspend); 367a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return nouveau_object_fini(&outp->base, suspend); 377a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs} 387a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 397a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsint 407a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs_nvkm_output_init(struct nouveau_object *object) 417a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs{ 427a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nvkm_output *outp = (void *)object; 437a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs int ret = nouveau_object_init(&outp->base); 447a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs if (ret == 0) 457a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs nv_ofuncs(outp->conn)->init(nv_object(outp->conn)); 467a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return 0; 477a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs} 487a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 497a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsvoid 507a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs_nvkm_output_dtor(struct nouveau_object *object) 517a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs{ 527a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nvkm_output *outp = (void *)object; 537a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs list_del(&outp->head); 547a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs nouveau_object_ref(NULL, (void *)&outp->conn); 557a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs nouveau_object_destroy(&outp->base); 567a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs} 577a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 587a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsint 597a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsnvkm_output_create_(struct nouveau_object *parent, 607a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_object *engine, 617a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_oclass *oclass, 627a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct dcb_output *dcbE, int index, 637a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs int length, void **pobject) 647a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs{ 657a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_bios *bios = nouveau_bios(engine); 667a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_i2c *i2c = nouveau_i2c(parent); 677a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_disp *disp = (void *)engine; 687a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nvbios_connE connE; 697a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nvkm_output *outp; 707a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs u8 ver, hdr; 717a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs u32 data; 727a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs int ret; 737a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 747a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject); 757a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs outp = *pobject; 767a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs if (ret) 777a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return ret; 787a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 797a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs outp->info = *dcbE; 807a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs outp->index = index; 81bf0eb89859439f016a1fab4cdf737c95f36dbb2eBen Skeggs outp->or = ffs(outp->info.or) - 1; 827a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 837a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n", 847a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ? 857a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs dcbE->sorconf.link : 0, dcbE->connector, dcbE->i2c_index, 867a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs dcbE->bus, dcbE->heads); 877a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 887a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs outp->port = i2c->find(i2c, outp->info.i2c_index); 897a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs outp->edid = outp->port; 907a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 917a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE); 927a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs if (!data) { 937a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs DBG("vbios connector data not found\n"); 947a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs memset(&connE, 0x00, sizeof(connE)); 957a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs connE.type = DCB_CONNECTOR_NONE; 967a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs } 977a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 987a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs ret = nouveau_object_ctor(parent, engine, nvkm_connector_oclass, 997a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs &connE, outp->info.connector, 1007a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs (struct nouveau_object **)&outp->conn); 1017a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs if (ret < 0) { 1027a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs ERR("error %d creating connector, disabling\n", ret); 1037a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return ret; 1047a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs } 1057a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 1067a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs list_add_tail(&outp->head, &disp->outp); 1077a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return 0; 1087a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs} 1097a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 1107a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsint 1117a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs_nvkm_output_ctor(struct nouveau_object *parent, 1127a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_object *engine, 1137a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_oclass *oclass, void *dcbE, u32 index, 1147a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nouveau_object **pobject) 1157a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs{ 1167a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs struct nvkm_output *outp; 1177a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs int ret; 1187a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 1197a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs ret = nvkm_output_create(parent, engine, oclass, dcbE, index, &outp); 1207a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs *pobject = nv_object(outp); 1217a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs if (ret) 1227a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return ret; 1237a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 1247a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs return 0; 1257a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs} 1267a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs 1277a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsstruct nouveau_oclass * 1287a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggsnvkm_output_oclass = &(struct nvkm_output_impl) { 1297a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .base = { 1307a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .handle = 0, 1317a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .ofuncs = &(struct nouveau_ofuncs) { 1327a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .ctor = _nvkm_output_ctor, 1337a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .dtor = _nvkm_output_dtor, 1347a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .init = _nvkm_output_init, 1357a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs .fini = _nvkm_output_fini, 1367a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs }, 1377a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs }, 1387a014a872914a6bb5af8b67eba603f8546794ab9Ben Skeggs}.base; 139