Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1029 serge 1
/*
2
 * Copyright 2007, 2008  Luc Verhaegen 
3
 * Copyright 2007, 2008  Matthias Hopf 
4
 * Copyright 2007, 2008 Egbert Eich   
5
 * Copyright 2007, 2008  Advanced Micro Devices, Inc.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
#endif
29
 
30
#include "xf86.h"
31
 
32
/* for usleep */
33
#if HAVE_XF86_ANSIC_H
34
# include "xf86_ansic.h"
35
#else
36
# include 
37
# include 
38
# include 
39
#endif
40
 
41
#include "rhd.h"
42
#include "edid.h"
43
 
44
#ifdef ATOM_BIOS
45
# include "rhd_atombios.h"
46
#endif
47
 
48
#include "rhd_connector.h"
49
#include "rhd_output.h"
50
#include "rhd_regs.h"
51
#include "rhd_monitor.h"
52
#include "rhd_card.h"
53
 
54
#include "xf86i2c.h"
55
#include "rhd_i2c.h"
56
 
57
 
58
 
59
/*
60
 *
61
 */
62
struct rhdHPD {
63
    Bool Stored;
64
    CARD32 StoreMask;
65
    CARD32 StoreEnable;
66
};
67
 
68
/*
69
 *
70
 */
71
void
72
RHDHPDSave(RHDPtr rhdPtr)
73
{
74
    struct rhdHPD *hpd = rhdPtr->HPD;
75
 
76
    RHDFUNC(rhdPtr);
77
 
78
    hpd->StoreMask = RHDRegRead(rhdPtr, DC_GPIO_HPD_MASK);
79
    hpd->StoreEnable = RHDRegRead(rhdPtr, DC_GPIO_HPD_EN);
80
 
81
    hpd->Stored = TRUE;
82
}
83
 
84
/*
85
 *
86
 */
87
void
88
RHDHPDRestore(RHDPtr rhdPtr)
89
{
90
  struct rhdHPD *hpd = rhdPtr->HPD;
91
 
92
  RHDFUNC(rhdPtr);
93
 
94
    if (hpd->Stored) {
95
	RHDRegWrite(rhdPtr, DC_GPIO_HPD_MASK, hpd->StoreMask);
96
	RHDRegWrite(rhdPtr, DC_GPIO_HPD_EN, hpd->StoreEnable);
97
    } else
98
	xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
99
		   "%s: no registers stored.\n", __func__);
100
}
101
 
102
/*
103
 *
104
 */
105
static void
106
RHDHPDSet(RHDPtr rhdPtr)
107
{
108
  RHDFUNC(rhdPtr);
109
 
110
    /* give the hw full control */
111
    RHDRegWrite(rhdPtr, DC_GPIO_HPD_MASK, 0);
112
    RHDRegWrite(rhdPtr, DC_GPIO_HPD_EN, 0);
113
 
114
  usleep(1);
115
}
116
 
117
/*
118
 *
119
 */
120
static Bool
121
RHDHPDCheck(struct rhdConnector *Connector)
122
{
123
    Bool ret;
124
 
125
    RHDFUNC(Connector);
126
 
127
    ret = RHDRegRead(Connector, DC_GPIO_HPD_Y);
128
    RHDDebug(Connector->scrnIndex, "%s returned: %x mask: %x\n",
129
	     __func__,ret, Connector->HPDMask);
130
 
131
    return (ret & Connector->HPDMask);
132
}
133
 
134
struct rhdCsState {
135
    int vga_cnt;
136
    int dvi_cnt;
137
};
138
 
139
/*
140
 *
141
 */
142
static char *
143
rhdConnectorSynthName(struct rhdConnectorInfo *ConnectorInfo,
144
		      struct rhdCsState **state)
145
{
146
  char *str = NULL;
147
    char *TypeName;
148
  char *str1, *str2;
149
    int cnt;
150
 
151
    ASSERT(state != NULL);
152
 
153
    if (!*state) {
154
	if (!(*state = xcalloc(sizeof(struct rhdCsState), 1)))
155
	    return NULL;
156
    }
157
    switch (ConnectorInfo->Type) {
158
	case RHD_CONNECTOR_NONE:
159
	    return NULL;
160
	case RHD_CONNECTOR_DVI:
161
	case RHD_CONNECTOR_DVI_SINGLE:
162
	    if (ConnectorInfo->Output[0] && ConnectorInfo->Output[1]) {
163
		TypeName = "DVI-I";
164
		cnt = ++(*state)->dvi_cnt;
165
	    } else if (ConnectorInfo->Output[0] == RHD_OUTPUT_DACA
166
		     || ConnectorInfo->Output[0] == RHD_OUTPUT_DACB
167
		     || ConnectorInfo->Output[1] == RHD_OUTPUT_DACA
168
		     || ConnectorInfo->Output[1] == RHD_OUTPUT_DACB
169
		) {
170
		if (ConnectorInfo->HPD == RHD_HPD_NONE) {
171
		    TypeName = "VGA";
172
		    cnt = ++(*state)->vga_cnt;
173
		} else {
174
		    TypeName = "DVI-A";
175
		    cnt = ++(*state)->dvi_cnt;
176
		}
177
	    } else {
178
		TypeName = "DVI-D";
179
		cnt = ++(*state)->dvi_cnt;
180
	    }
181
	    str = xalloc(12);
182
	    snprintf(str, 11, "%s %i",TypeName, cnt);
183
	    return str;
184
 
185
    case RHD_CONNECTOR_VGA:
186
	    str = xalloc(10);
187
      snprintf(str, 9, "VGA %i",++(*state)->vga_cnt);
188
	    return str;
189
 
190
    case RHD_CONNECTOR_PANEL:
191
	    str = xalloc(10);
192
	    snprintf(str, 9, "PANEL");
193
	    return str;
194
 
195
    case RHD_CONNECTOR_TV:
196
	    str1 = xstrdup(ConnectorInfo->Name);
197
	    str = xalloc(20);
198
      str2 = strchr(str1, ' ');
199
      if (str2) *(str2) = '\0';
200
        snprintf(str, 20, "TV %s",str1);
201
	    xfree(str1);
202
	    return str;
203
 
204
	case RHD_CONNECTOR_PCIE: /* should never get here */
205
	    return NULL;
206
    }
207
    return NULL;
208
}
209
 
210
/*
211
 *
212
 */
213
Bool
214
RHDConnectorsInit(RHDPtr rhdPtr, struct rhdCard *Card)
215
{
216
  struct rhdConnectorInfo *ConnectorInfo;
217
  struct rhdConnector *Connector;
218
  struct rhdOutput *Output;
219
  struct rhdCsState *csstate = NULL;
220
  int i, j, k, l, hpd;
221
  Bool InfoAllocated = FALSE;
222
 
223
    RHDFUNC(rhdPtr);
224
 
225
    /* Card->ConnectorInfo is there to work around quirks, so check it first */
226
    if (Card && (Card->ConnectorInfo[0].Type != RHD_CONNECTOR_NONE)) {
227
    ConnectorInfo = Card->ConnectorInfo;
228
	xf86DrvMsg(rhdPtr->scrnIndex, X_INFO,
229
		   "ConnectorInfo from quirk table:\n");
230
	RhdPrintConnectorInfo (rhdPtr, ConnectorInfo);
231
    } else {
232
#ifdef ATOM_BIOS
233
	/* common case */
234
    AtomBiosArgRec data;
235
    AtomBiosResult result;
236
 
237
  data.chipset = rhdPtr->ChipSet;
238
  result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
239
             ATOMBIOS_GET_CONNECTORS, &data);
240
	if (result == ATOM_SUCCESS) {
241
	    ConnectorInfo = data.ConnectorInfo;
242
	    InfoAllocated = TRUE;
243
	} else
244
#endif
245
    {
246
	    xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: Failed to retrieve "
247
		       "Connector information.\n", __func__);
248
	    return FALSE;
249
    }
250
  }
251
 
252
    /* Init HPD */
253
    rhdPtr->HPD = xnfcalloc(sizeof(struct rhdHPD), 1);
254
  RHDHPDSave(rhdPtr);
255
  RHDHPDSet(rhdPtr);
256
 
257
    for (i = 0, j = 0; i < RHD_CONNECTORS_MAX; i++) {
258
    if (ConnectorInfo[i].Type == RHD_CONNECTOR_NONE)
259
      continue;
260
 
261
	RHDDebug(rhdPtr->scrnIndex, "%s: %d (%s) type %d, ddc %d, hpd %d\n",
262
              __func__, i, ConnectorInfo[i].Name, ConnectorInfo[i].Type,
263
		 ConnectorInfo[i].DDC, ConnectorInfo[i].HPD);
264
 
265
	Connector = xnfcalloc(sizeof(struct rhdConnector), 1);
266
	Connector->scrnIndex = rhdPtr->scrnIndex;
267
    Connector->Type = ConnectorInfo[i].Type;
268
    Connector->Name = rhdConnectorSynthName(&ConnectorInfo[i], &csstate);
269
 
270
	/* Get the DDC bus of this connector */
271
	if (ConnectorInfo[i].DDC != RHD_DDC_NONE) {
272
	    RHDI2CDataArg data;
273
	    int ret;
274
 
275
	    data.i = ConnectorInfo[i].DDC;
276
	    ret = RHDI2CFunc(rhdPtr->scrnIndex,
277
			     rhdPtr->I2C, RHD_I2C_GETBUS, &data);
278
	    if (ret == RHD_I2C_SUCCESS)
279
        Connector->DDC = data.i2cBusPtr;
280
    }
281
 
282
	/* attach HPD */
283
    hpd = ConnectorInfo[i].HPD;
284
	switch (rhdPtr->hpdUsage) {
285
      case RHD_HPD_USAGE_OFF:
286
      case RHD_HPD_USAGE_AUTO_OFF:
287
        hpd = RHD_HPD_NONE;
288
        break;
289
      case RHD_HPD_USAGE_SWAP:
290
      case RHD_HPD_USAGE_AUTO_SWAP:
291
	    switch (hpd) {
292
          case RHD_HPD_0:
293
            hpd = RHD_HPD_1;
294
            break;
295
          case RHD_HPD_1:
296
            hpd = RHD_HPD_0;
297
            break;
298
        }
299
        break;
300
      default:
301
        break;
302
    }
303
	switch(hpd) {
304
      case RHD_HPD_0:
305
        Connector->HPDMask = 0x00000001;
306
        Connector->HPDCheck = RHDHPDCheck;
307
        break;
308
      case RHD_HPD_1:
309
        Connector->HPDMask = 0x00000100;
310
        Connector->HPDCheck = RHDHPDCheck;
311
        break;
312
      case RHD_HPD_2:
313
        Connector->HPDMask = 0x00010000;
314
        Connector->HPDCheck = RHDHPDCheck;
315
        break;
316
	case RHD_HPD_3:
317
	    Connector->HPDMask = 0x01000000;
318
	    Connector->HPDCheck = RHDHPDCheck;
319
	    break;
320
      default:
321
        Connector->HPDCheck = NULL;
322
        break;
323
    }
324
 
325
	/* create Outputs */
326
	for (k = 0; k < 2; k++) {
327
	    if (ConnectorInfo[i].Output[k] == RHD_OUTPUT_NONE)
328
        continue;
329
 
330
	    /* Check whether the output exists already */
331
	    for (Output = rhdPtr->Outputs; Output; Output = Output->Next)
332
        if (Output->Id == ConnectorInfo[i].Output[k])
333
          break;
334
 
335
	    if (!Output) {
336
		if (!RHDUseAtom(rhdPtr, NULL, atomUsageOutput)) {
337
		switch (ConnectorInfo[i].Output[k]) {
338
          case RHD_OUTPUT_DACA:
339
            Output = RHDDACAInit(rhdPtr);
340
            RHDOutputAdd(rhdPtr, Output);
341
            break;
342
          case RHD_OUTPUT_DACB:
343
            Output = RHDDACBInit(rhdPtr);
344
            RHDOutputAdd(rhdPtr, Output);
345
            break;
346
          case RHD_OUTPUT_TMDSA:
347
            Output = RHDTMDSAInit(rhdPtr);
348
            RHDOutputAdd(rhdPtr, Output);
349
            break;
350
          case RHD_OUTPUT_LVTMA:
351
            Output = RHDLVTMAInit(rhdPtr, ConnectorInfo[i].Type);
352
            RHDOutputAdd(rhdPtr, Output);
353
            break;
354
		    case RHD_OUTPUT_DVO:
355
			Output = RHDDDIAInit(rhdPtr);
356
		    if (Output)
357
			RHDOutputAdd(rhdPtr, Output);
358
		    break;
359
		case RHD_OUTPUT_KLDSKP_LVTMA:
360
		case RHD_OUTPUT_UNIPHYA:
361
		case RHD_OUTPUT_UNIPHYB:
362
		    Output = RHDDIGInit(rhdPtr, ConnectorInfo[i].Output[k], ConnectorInfo[i].Type);
363
		    RHDOutputAdd(rhdPtr, Output);
364
		    break;
365
          default:
366
		    xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
367
				   "%s: unhandled output id: %d. Trying fallback to AtomBIOS\n", __func__,
368
			       ConnectorInfo[i].Output[k]);
369
            break;
370
        }
371
	    }
372
#ifdef ATOM_BIOS
373
		if (!Output) {
374
		    Output = RHDAtomOutputInit(rhdPtr, ConnectorInfo[i].Type,
375
					       ConnectorInfo[i].Output[k]);
376
		    if (Output)
377
			RHDOutputAdd(rhdPtr, Output);
378
		}
379
#endif
380
	    }
381
 
382
	    if (Output) {
383
		xf86DrvMsg(rhdPtr->scrnIndex, X_PROBED,
384
			   "Attaching Output %s to Connector %s\n",
385
			   Output->Name, Connector->Name);
386
        for (l = 0; l < 2; l++)
387
		    if (!Connector->Output[l]) {
388
            Connector->Output[l] = Output;
389
            break;
390
          }
391
	    }
392
    }
393
 
394
    rhdPtr->Connector[j] = Connector;
395
    j++;
396
  }
397
  if (csstate)
398
	xfree(csstate);
399
 
400
    /* Deallocate what atombios code allocated */
401
    if (ConnectorInfo && InfoAllocated) {
402
    for (i = 0; i < RHD_CONNECTORS_MAX; i++)
403
	    if (ConnectorInfo[i].Type != RHD_CONNECTOR_NONE)
404
		xfree(ConnectorInfo[i].Name);
405
	/* Don't free the Privates as they are hooked into the rhdConnector structures !!! */
406
	xfree(ConnectorInfo);
407
  }
408
 
409
  RHDHPDRestore(rhdPtr);
410
 
411
  return (j && 1);
412
}
413
 
414
/*
415
 *
416
 */
417
void
418
RHDConnectorsDestroy(RHDPtr rhdPtr)
419
{
420
  struct rhdConnector *Connector;
421
  int i;
422
 
423
  RHDFUNC(rhdPtr);
424
 
425
    for (i = 0; i < RHD_CONNECTORS_MAX; i++) {
426
    Connector = rhdPtr->Connector[i];
427
	if (Connector) {
428
	    if (Connector->Monitor)
429
		RHDMonitorDestroy(Connector->Monitor);
430
	    xfree(Connector->Name);
431
	    xfree(Connector);
432
    }
433
  }
434
}
435
 
436
/*
437
 *
438
 */
439
void
440
RhdPrintConnectorInfo(RHDPtr rhdPtr, struct rhdConnectorInfo *cp)
441
{
442
  int n;
443
  int scrnIndex=0;
444
 
445
  const char *c_name[] =
446
	{ "RHD_CONNECTOR_NONE", "RHD_CONNECTOR_VGA", "RHD_CONNECTOR_DVI",
447
	  "RHD_CONNECTOR_DVI_SINGLE", "RHD_CONNECTOR_PANEL",
448
	  "RHD_CONNECTOR_TV", "RHD_CONNECTOR_PCIE" };
449
 
450
  const char *ddc_name[] =
451
	{ "RHD_DDC_0", "RHD_DDC_1", "RHD_DDC_2", "RHD_DDC_3", "RHD_DDC_4" };
452
 
453
  const char *hpd_name_normal[] =
454
	{ "RHD_HPD_NONE", "RHD_HPD_0", "RHD_HPD_1", "RHD_HPD_2", "RHD_HPD_3" };
455
  const char *hpd_name_off[] =
456
	{ "RHD_HPD_NONE", "RHD_HPD_NONE /*0*/", "RHD_HPD_NONE /*1*/", "RHD_HPD_NONE /*2*/", "RHD_HPD_NONE /*3*/" };
457
    const char *hpd_name_swapped[] =
458
	{ "RHD_HPD_NONE", "RHD_HPD_1 /*swapped*/", "RHD_HPD_0 /*swapped*/", "RHD_HPD_2", "RHD_HPD_3" };
459
 
460
  const char *output_name[] =
461
	{ "RHD_OUTPUT_NONE", "RHD_OUTPUT_DACA", "RHD_OUTPUT_DACB", "RHD_OUTPUT_TMDSA",
462
	  "RHD_OUTPUT_LVTMA", "RHD_OUTPUT_DVO", "RHD_OUTPUT_KLDSKP_LVTMA",
463
	  "RHD_OUTPUT_UNIPHYA", "RHD_OUTPUT_UNIPHYB", "RHD_OUTPUT_UNIPHYC", "RHD_OUTPUT_UNIPHYD",
464
	  "RHD_OUTPUT_UNIPHYE", "RHD_OUTPUT_UNIPHYF" };
465
  const char **hpd_name;
466
 
467
    switch (rhdPtr->hpdUsage) {
468
    case RHD_HPD_USAGE_OFF:
469
    case RHD_HPD_USAGE_AUTO_OFF:
470
      hpd_name = hpd_name_off;
471
      break;
472
    case RHD_HPD_USAGE_SWAP:
473
    case RHD_HPD_USAGE_AUTO_SWAP:
474
      hpd_name = hpd_name_swapped;
475
      break;
476
    default:
477
     hpd_name = hpd_name_normal;
478
     break;
479
  }
480
 
481
    for (n = 0; n < RHD_CONNECTORS_MAX; n++) {
482
    if (cp[n].Type == RHD_CONNECTOR_NONE)
483
	    break;
484
	xf86DrvMsg(scrnIndex, X_INFO, "Connector[%i] {%s, \"%s\", %s, %s, { %s, %s } }\n",
485
		   n, c_name[cp[n].Type], cp[n].Name,
486
		   cp[n].DDC == RHD_DDC_NONE ? "RHD_DDC_NONE" : ddc_name[cp[n].DDC],
487
		   hpd_name[cp[n].HPD], output_name[cp[n].Output[0]],
488
		   output_name[cp[n].Output[1]]);
489
  }
490
}
491
 
492
/*
493
 * Should we enable HDMI on this connector?
494
 */
495
Bool RHDConnectorEnableHDMI(struct rhdConnector *Connector)
496
{
497
    RHDPtr rhdPtr = RHDPTRI(Connector);
498
    RHDFUNC(rhdPtr);
499
 
500
    /* check if user forced HDMI on this connector */
501
//    switch(RhdParseBooleanOption(&rhdPtr->hdmi, Connector->Name)) {
502
//	case RHD_OPTION_ON:
503
//	case RHD_OPTION_DEFAULT:
504
//	    xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "Enabling HDMI on %s because of config option\n", Connector->Name);
505
//	    return TRUE;
506
//	case RHD_OPTION_OFF:
507
//	    xf86DrvMsg(rhdPtr->scrnIndex, X_INFO, "Disabling HDMI on %s because of config option\n", Connector->Name);
508
//	    return FALSE;
509
//	case RHD_OPTION_NOT_SET:
510
//	    /* ask connected monitor if it supports HDMI */
511
//	    /* TODO: Not implemented yet! */
512
//	    return FALSE;
513
//    }
514
 
515
    return FALSE;
516
}