Jump to content

ATI Framebuffer development


Slice
 Share

466 posts in this topic

Recommended Posts

Waiting for your good news. ;)
Still no :P
itvview.c contains i2c subaddress, don't know how to handle it yet.

Here

DDCRead_DDC2(CARD8 line, void* map, int start, int len)
{
unsigned char W_Buffer[2];
int w_bytes;
unsigned char *R_Buffer = &EDID[0];
int i;

I2CSlaveAddr SlaveAddr = 0xA0;   -- i2c subaddress
int prescale = rhdGetI2CPrescale();

But, I happenly found that IONDRVSupport has no problem with output to TV in mirror mode, though display preference has no information of multilple displays. IORegistry contains: display@0 and display@0,1

It is a non-useful device with class code 0x038000. Don't attach them!

You can get multiple displays if write into natit (or else..) strings like

@0,name

@1,name

Thus you will have two framebuffers differing in ioreg

"IOFBDependentIndex" = 0x0 or 0x1

And there might be information about real connections

"connector-type" =

"display-connect-flags" =

I propose that the property

"AAPL,vram-memory" =

must be different for two framebuffers to have different pictures but I can't check.

 

Did you have ATITVOut.kext with Intel flavour? Thanks to Krazubu!

If use Callisto patch, it will cause a KP if TV is connected.

One more stone thrown into Callisto :P

Link to comment
Share on other sites

	 I2CSlaveAddr SlaveAddr = 0xA0;   -- i2c subaddress

SlaveAddr is sendAddress, but not subaddress as you can see in i2cexample.c (also in tools folder).

void EDIDRead( IOI2CConnectRef connect, Boolean save )
{
kern_return_t	kr;
IOI2CRequest	request;
UInt8		data[128];
int		 i;

bzero( &request, sizeof(request) );

request.commFlags				= 0;

request.sendAddress			= 0xA0;

Did you have ATITVOut.kext with Intel flavour? Thanks to Krazubu!

Any link for a working version of this?

 

Edit:

Just put subAddress as the first data byte to write. However, what itvview.c does is only save random bytes to tv and read them back through i2c to make sure i2c channel is working if the bytes read back are not changed.

Link to comment
Share on other sites

Any link for a working version of this?

Post N52 here. And link is still alive.

When you install the utility, or open by Pacifist, you may find ATITVOut. In kextstat I see that it loaded but I make no any test yet because no any other monitors and TV near to my working place.

Edit:

Just put subAddress as the first data byte to write. However, what itvview.c does is only save random bytes to tv and read them back through i2c to make sure i2c channel is working if the bytes read back are not changed.

I didn't check, sorry. May be you are right. But not all I2C bus return the same value as written! For a what? It may be some kind of RAM or register space. Don't know.

 

I am busy to adjust Linux sources to The Project.

Link to comment
Share on other sites

C++ is very complex language. I understand that OpenATI project is wrong defining class ATIDriver.

Here there is working one without any hardware function. Very good template.

Now we can add functions to ATIDriver or override some framebuffer members.

Look xbench results before

	Quartz Graphics Test	41.38	
	Line	34.74	2.31 Klines/sec [50% alpha]
	Rectangle	35.67	10.65 Krects/sec [50% alpha]
	Circle	35.46	2.89 Kcircles/sec [50% alpha]
	Bezier	58.89	1.49 Kbeziers/sec [50% alpha]
	Text	53.05	3.32 Kchars/sec
OpenGL Graphics Test	24.09	
	Spinning Squares	24.09	30.57 frames/sec
User Interface Test	55.41	
	Elements	55.41	254.31 refresh/sec

and after

	Quartz Graphics Test	60.39	
	Line	48.79	3.25 Klines/sec [50% alpha]
	Rectangle	59.06	17.63 Krects/sec [50% alpha]
	Circle	57.87	4.72 Kcircles/sec [50% alpha]
	Bezier	69.16	1.74 Kbeziers/sec [50% alpha]
	Text	73.38	4.59 Kchars/sec
OpenGL Graphics Test	23.89	
	Spinning Squares	23.89	30.30 frames/sec
User Interface Test	81.26	
	Elements	81.26	372.93 refresh/sec

What is happen? This is nearly empty class! Other interrupts? No IOPEFNDRV calls?

Link to comment
Share on other sites

Next step.

 

This project contains Radeon initialization and BIOS interpretation. So I get internal structures needed to make switch resolution. Final cut is to do the procedure :D

 

The problems:

1. For my shared memory I want to change physical address of framebuffer from PCI address 0xd0000000 to kernel space 0x38000000. I see method

IOReturn IOFramebuffer::doSetup( bool full )

that is not present in IONDRVFramebuffer. How to influence?

For users with dedicated memory there is no problem.

 

2. GetConnectors

from BIOS I get static array of connectors.

from registry I get index of framebuffer

How can I know that framebuffer is connected to bus N?

Joblo said

/*-------------------------------------------------------------------------

* Probe physical connection of a CRT. This code comes from XFree

* as well and currently is only implemented for the CRT DAC, the

* code for the TVDAC is commented out in XFree as "non working"

*/

What to do? I have TVDAC namely.

From Linux codes I see my connector is PROPRIETARY.

And I have poor connectorInfo from BIOS even with latest codes.

I simply write rinfo->mon1_type = MT_LCD; despite on all previous calculations.

 

3. R500 compatibility. Cause I still use Joblo's sources my project is intended for R200-R400.

Needs to rewrite INPLL, OUTPLL, memory mapping (MC_FB_LOCATION) etc. according to similar Linux codes. XF project must work for R500-R600!

 

4. I2C bus routing I didn't implement because I can't check its. No problem! Simply get dong's sources RadeonDump and use it at command

cscGetCommunicationInfo

 

The kext is still works with ATILead but without switch resolutions.

Take into account that I inject value

@0,address

0xd0000000

It is my own address. It is not good idea to write it manually. Simply delete this key!

 

What about ATILead compatibility with R500-R600? I think it is not problem for dong :P

Link to comment
Share on other sites

I hope this is the right thread.

 

Slice i got RadeonPCI.kext and Radeon Dump.

 

Here is the dump for you

OK, as you see your DevID is really 5a62

0180: 02 10 62 5A 00 00 18 00 00 00 00 03 68 00 32 08 ..bZ........h.2.

0190: 00 80 00 00 41 54 49 20 52 41 44 45 4F 4E 20 58 ....ATI RADEON X

01A0: 50 52 45 53 53 20 32 30 30 4D 20 53 65 72 69 65 PRESS 200M Serie

01B0: 73 00 9F 9C 9D 70 FF FF FF FF 1E FD 01 02 FF FF s....p..........

Now get EDID

./RadeonDump -i

and registers dump

./RadeonDump -r 0,300

Link to comment
Share on other sites

2 Littlesteve

Thank you for the dump. If you have no success with getting EDID then try to use other version of RadeonDump. (can you compile?).

Be ready for new tests.

 

2 dong

How do you think what is reversedDAC? If it is Digital-to-Analog-Converter then reversed may meen that on I2C bus HIGH=0 and LOW=1 as you use in RadeonDump. (?) Different buses - different DAC?

What is the difference between X1400 and mobile version? ReversedDAC?

Can you get (sorry I forget) EDID of LCD monitor with X1400 by software I2C?

I have proposition to you.

I can make binary patch for ATY_Caretta to use software I2C with your settings.

Look

		lea	eax, [ebp+var_9]
	or	byte ptr [eax],	10h   // enable clock bit  (1<<4)
	cmp	[ebp+var_1C], 0   // arg == 0 ?
	jz	short loc_1D1ED   // if yes
	lea	eax, [ebp+var_9]
	or	byte ptr [eax],	2  // (if arg==1)  v |= (1<<1) //set clock
	jmp	short loc_1D1F3
; ---------------------------------------------------------------------------

loc_1D1ED:; CODE XREF: _DDCSetClock+20j
	lea	eax, [ebp+var_9]
	and	byte ptr [eax],	0FDh   // v &= 0xfd   //clear bit (1<<1)

loc_1D1F3:; CODE XREF: _DDCSetClock+28j

as you see it uses direct DAC (HIGH=1 LOW=0)

CLK_EN=10

DATA_EN=20

CLK_OUT=2

DATA_OUT=4

CLK_IN=2

DATA_IN=4

but I don't see registers.

Here registers for three buses

		cmp	[ebp+var_24], 2
	jz	short loc_1BBDA
	cmp	[ebp+var_24], 3
	jz	short loc_1BBEE
	cmp	[ebp+var_24], 1
	jz	short loc_1BBC6
	jmp	short loc_1BC00
; ---------------------------------------------------------------------------

loc_1BBC6:		; CODE XREF: _COMSetSense+A6j
	mov	[ebp+var_E], 7E48h
	mov	[ebp+var_C], 7E40h
	mov	[ebp+var_A], 7E44h
	jmp	short loc_1BC00
; ---------------------------------------------------------------------------

loc_1BBDA:		; CODE XREF: _COMSetSense+9Aj
	mov	[ebp+var_E], 7E58h
	mov	[ebp+var_C], 7E50h
	mov	[ebp+var_A], 7E54h
	jmp	short loc_1BC00
; ---------------------------------------------------------------------------

loc_1BBEE:		; CODE XREF: _COMSetSense+A0j
	mov	[ebp+var_E], 7E68h
	mov	[ebp+var_C], 7E60h
	mov	[ebp+var_A], 7E64h

I don't know what to patch in hardware I2C (edid_digital). Have you an idea?

 

Another thing you can check

		mov	[ebp+var_28], offset aNoneEdid; "NONE,EDID"
	mov	[ebp+var_24], offset aTvEdid; "TV,EDID"
	mov	[ebp+var_20], offset aDfp1Edid; "DFP1,EDID"
	mov	[ebp+var_1C], offset aDfp2Edid; "DFP2,EDID"
	mov	[ebp+var_18], offset aCrt1Edid; "CRT1,EDID"
	mov	[ebp+var_14], offset aCrt2Edid; "CRT2,EDID"
	mov	[ebp+var_10], offset aLvdsEdid; "LVDS,EDID"
	mov	[ebp+var_C], offset aCompEdid;	"COMP,EDID"

It means you can inject EDID by Natit?

Link to comment
Share on other sites

What is the difference between X1400 and mobile version? ReversedDAC?

There shouldn't be a difference, as the X1400 is only available in its mobile version.

 

Anyway, I'm open to running a few tests. I saw the words "patched" and "ATY_Caretta" in the same post, meaning LVDS support might just come around.

Link to comment
Share on other sites

How do you think what is reversedDAC? If it is Digital-to-Analog-Converter then reversed may meen that on I2C bus HIGH=0 and LOW=1 as you use in RadeonDump. (?) Different buses - different DAC?
Comments in radeon-ati source show that reversedDAC matters in CRTC->DAC mapping.

"CRTC1 could be driving either DAC or both DACs.

CRT+CRT: CRTC1->TV DAC, CRTC2->Primary DAC

DFP/LCD+CRT: CRTC2->TV DAC, CRTC2->Primary DAC.

Some boards have two DACs reversed or don't even have a primary DAC,

this is reflected in pRADEONEnt->ReversedDAC. And radeon 7200 doesn't have a second DAC."

Also "Bool ReversedDAC = TRUE;" means /* TVDAC used as primary dac */

What is the difference between X1400 and mobile version? ReversedDAC?

Can you get (sorry I forget) EDID of LCD monitor with X1400 by software I2C?

My x1400 is itself a mobile card, no reversedDAC. I have no problem to get EDID by either hardware or software I2Cs. The LVDS has DDC-2 channel (named by linux code, ATINDRV call it DDC3).
loc_1BBC6: ; CODE XREF: _COMSetSense+A6j

mov [ebp+var_E], 7E48h

mov [ebp+var_C], 7E40h

mov [ebp+var_A], 7E44h

jmp short loc_1BC00

; ---------------------------------------------------------------------------

 

loc_1BBDA: ; CODE XREF: _COMSetSense+9Aj

mov [ebp+var_E], 7E58h

mov [ebp+var_C], 7E50h

mov [ebp+var_A], 7E54h

jmp short loc_1BC00

; ---------------------------------------------------------------------------

 

loc_1BBEE: ; CODE XREF: _COMSetSense+A0j

mov [ebp+var_E], 7E68h

mov [ebp+var_C], 7E60h

mov [ebp+var_A], 7E64h[/code]

These three registers, 7E40, 7E50, 7E60 are just the normal ones been used in linux source for R5xx/6xx cards. It may turn out the same results. ie, works for me, but won't for others.
I don't know what to patch in hardware I2C (edid_digital). Have you an idea?
I still have difficulty in reading asm codes even ida has made a great job in providing useful informations.
It means you can inject EDID by Natit?
In addition to EDID, Caretta may lack the whole ability to handle LVDS.
Link to comment
Share on other sites

In addition to EDID, Caretta may lack the whole ability to handle LVDS.

It does lack this feature. Wormy is the only handler of LVDS.

Link to comment
Share on other sites

I have no problem to get EDID by either hardware or software I2Cs. The LVDS has DDC-2 channel.

These three registers, 7E40, 7E50, 7E60 are just the normal ones been used in linux source for R5xx/6xx cards. It may turn out the same results. ie, works for me, but won't for others.

Please clarify. You can get EDID for LCD with register 7E50 ? RadeonDump from post #135?

I still have difficulty in reading asm codes even ida has made a great job in providing useful informations.

In addition to EDID, Caretta may lack the whole ability to handle LVDS.

I don't know what is mean. I still continue to study.

In Tiger 10.4.6 I have only one ATINDRV which is ATY_Wormy with more codes then plugins from 10.4.9 such as caretta. May be it is more universal?

Link to comment
Share on other sites

2 Littlesteve

Thank you for the dump. If you have no success with getting EDID then try to use other version of RadeonDump. (can you compile?).

Be ready for new tests.

 

I found another copy of RadeonDump and i got the same result... no EDID.

 

on the note of compiling, what exactly do i need (Xcode?). i have done alot of compiling under linux, but the same commands dont work under mac :blink: (is there no handling for make files?).

 

also i cant seem to find GCC if you can point me in the direction of what i need i would be very grateful

Link to comment
Share on other sites

Please clarify. You can get EDID for LCD with register 7E50 ? RadeonDump from post #135?
I can get EDID of my x1400 LVDS panel through 7E60 by any RadeonDump I posted for i2c dumping. However, the ATOM BIOS contains wrong connector infomation which makes the original linux source to initilize i2c from BIOS not usable. The i2c setup is actually use default one (not depend on BIOS) and it just works. Good news is that the legacy BIOS of x600 on my Dell desktop has no problem to setup correct i2c connection and read the analog LCD EDID.
In Tiger 10.4.6 I have only one ATINDRV which is ATY_Wormy with more codes then plugins from 10.4.9 such as caretta. May be it is more universal?
Yes, ATY_Wormy is fully functional, but not ATY_Caretta which is only written for a mac server. Only if both sources are available, that we can borrow LVDS handling code from Wormy to Caretta.
also i cant seem to find GCC if you can point me in the direction of what i need i would be very grateful
Yes, you need xcode to provide GCC.
Link to comment
Share on other sites

2 dong

As I understand you are successful with software I2C at the following settings

		info.ddc_i2c[2] = atom_setup_i2c_bus(0x7e60);
....
i2c.put_clk_mask = (1 << 0);
i2c.put_data_mask = (1 << 8);
i2c.get_clk_mask = (1 << 0);
i2c.get_data_mask = (1 << 8);
i2c.mask_clk_mask = (1 << 0);
i2c.mask_data_mask = (1 << 8);
}
i2c.mask_clk_reg = ddc_line;
i2c.mask_data_reg = ddc_line;
i2c.put_clk_reg = ddc_line + 0x8;
i2c.put_data_reg = ddc_line + 0x8;
i2c.get_clk_reg = ddc_line + 0xc;
i2c.get_data_reg = ddc_line + 0xc;

The last line arise me a question

get_data_reg=7e6c?

Compare with Wormy

loc_215D3:			; CODE XREF: _COMSetSense+A0j
	mov	[ebp+var_E], 7E68h
	mov	[ebp+var_C], 7E60h
	mov	[ebp+var_A], 7E64h

Now read RV630 AMD document

DC_GPIO_DDC3_MASK - RW - 32 bits - [GpuF0MMReg:0x7E60]

Field Name Bits Default Description

DC_GPIO_DDC3CLK_MASK 0 0x0 Enable/Disable GPIO functionality on DDC3CLK pad

0=Pad Driven by Hardware - Normal Operation

1=Pad Controlled by Software through associated GPIO

registers. Pad values generated by hardware are overridden.

DC_GPIO_DDC3DATA_MASK 8 0x0 Enable/Disable GPIO functionality on DDC3DATA pad

0=Pad Driven by Hardware - Normal Operation

1=Pad Controlled by Software through associated GPIO

registers. Pad values generated by hardware are overridden.

DC_GPIO_DDC3DATA_PD_EN 12 0x0 Set to 1 to enable pulldown on DDC3DATA pad

0=Disable

1=Enable

DC_GPIO_DDC3DATA_PU_EN 14 0x0 Set to 1 to enable pullup on DDC3DATA pad

0=Disable

1=Enable

Control GPIO functionality of the DDC3 pads - all fields are active high.

DC_GPIO_DDC3_A - RW - 32 bits - [GpuF0MMReg:0x7E64]

Field Name Bits Default Description

DC_GPIO_DDC3CLK_A 0 0x0 Asynchronous input for DDC3CLK when

DC_GPIO_DDC3CLK_MASK = 1.

DC_GPIO_DDC3DATA_A 8 0x0 Asynchronous input for DDC3DATA when

DC_GPIO_DDC3DATA_MASK = 1.

Asynchronous inputs for the DDC3 pads when the GPIO functionality is enabled by the

DC_GPIO_DDC3_MASK register.

 

DC_GPIO_DDC3_EN - RW - 32 bits - [GpuF0MMReg:0x7E68]

Field Name Bits Default Description

DC_GPIO_DDC3CLK_EN 0 0x0 Output enable for DDC3CLK when

DC_GPIO_DDC3CLK_MASK = 1.

DC_GPIO_DDC3DATA_EN 8 0x0 Output enable for DDC3DATA when

DC_GPIO_DDC3DATA_MASK = 1.

Output enable values for the DDC3 pads when the GPIO functionality is enabled by the DC_GPIO_DDC3_MASK register.

 

DC_GPIO_DDC3_Y - RW - 32 bits - [GpuF0MMReg:0x7E6C]

Field Name Bits Default Description

DC_GPIO_DDC3CLK_Y ® 0 0x0 Value on DDC3CLK pad.

DC_GPIO_DDC3DATA_Y ® 8 0x0 Value on DDC3DATA pad.

Output values for the DDC3 pads.

I don't understand this.

Why you use

val |= (Clock ? 0:pRADEONI2CBus->put_clk_mask);

???

If (clock == 1) you write 0?

Link to comment
Share on other sites

the ATOM BIOS contains wrong connector infomation which makes the original linux source to initilize i2c from BIOS not usable. The i2c setup is actually use default one (not depend on BIOS) and it just works. Good news is that the legacy BIOS of x600 on my Dell desktop has no problem to setup correct i2c connection and read the analog LCD EDID.

I am not satisfied also with LegacyBIOS connector information. What to do?

I can make Framebuffer only for me if I manually set the information but... I will be bad dog in this case.

Set IORegistry values like "display-connect" or "NVCAP"?

Link to comment
Share on other sites

I check carefully ATY_Wormy codes and found that it uses exactly the same algorithm as you.

But for set clock

outreg(0x7360, 0x101);

outreg(0x7364, 0);

outreg(0x7368, clock?0:1);

Is it the same?

Before enable we need to set output - my mistake!

Link to comment
Share on other sites

Slice, you are really an excellent ASM decoder! I need check the source code to say anything.

 

A initial dig into the Caretta ASM code show that only DDC1 is used for connector. DDC3 is used for some special thing. In Wommy, both DDC1, DDC3 are used for connectors.

Link to comment
Share on other sites

At last I connect second monitor to my laptop. It is ViewSonic P655 - DDC CRT. Sure!

I can't get EDID with any version of RadeonDump ;) . Mistakes!

 

Good news. I understand how to know about connected monitors.

	tmp = INREG(BIOS_4_SCRATCH);
IOLog("ATIFB: radeon_get_moninfo: bios 4 scratch = %x\n", tmp);

if (rinfo->has_CRTC2) {
	/* primary DVI port */
	if (tmp & 0x08)
		rinfo->dviDisp_type = MT_DFP;
	else if (tmp & 0x4)
		rinfo->dviDisp_type = MT_LCD;
	else if (tmp & 0x200)
		rinfo->dviDisp_type = MT_CRT;
	else if (tmp & 0x10)
		rinfo->dviDisp_type = MT_CTV;
	else if (tmp & 0x20)
		rinfo->dviDisp_type = MT_STV;

	/* secondary CRT port */
	if (tmp & 0x2)
		rinfo->crtDisp_type = MT_CRT;
	else if (tmp & 0x800)
		rinfo->crtDisp_type = MT_DFP;
	else if (tmp & 0x400)
		rinfo->crtDisp_type = MT_LCD;
	else if (tmp & 0x1000)
		rinfo->crtDisp_type = MT_CTV;
	else if (tmp & 0x2000)
		rinfo->crtDisp_type = MT_STV;
	else
		rinfo->crtDisp_type = MT_NONE;
} else {
	rinfo->dviDisp_type = MT_NONE;

	tmp = INREG(FP_GEN_CNTL);

	if (tmp & FP_EN_TMDS)
		rinfo->crtDisp_type = MT_DFP;
	else
		rinfo->crtDisp_type = MT_CRT;
}

With only LCD I have BIOS_4_SCRATCH=01000004 and BIOS_5_SCRATCH=01000001

With 2 monitors I have 03000006 and 03000003

It means first monitor = MT_LCD

second monitor (when connected) = MT_CRT

 

We may write into injector two instance of framebuffer.

0,name

1,name

If second monitor is not present then return false after check and work with one framebuffer. That all for connectors problem!

Linux's BIOS reading can say about ddc register. I obtain that CRT connector must use GPIO_VGA_DDC=0x60.

Before connect I have (0x60)=0x300

After connect I have (0x60)=0x100

CLOCK_INPUT became low!

No any information about LCD. It seems to be really non-ddc laptop LCD. OK! I can inject EDID.

I still don't know why we need to calculate dac_type or tmds_type.

 

Next observation. Connect TV. No screen output yet. I hope to do it.

BIOS_4_SCRATCH=01000024 and BIOS_5_SCRATCH=03000001

So code above is not correct in this case. Bit 20 = MT_STV. May be. But it is second device and not primary.

Bits 24 and 25 is not described anywhere but we see what is it.

 

Wait...

Link to comment
Share on other sites

No wonder your card is also a problem for linux system. Really hard to defeat. ;)

We may write into injector two instance of framebuffer.

0,name

1,name

If second monitor is not present then return false after check and work with one framebuffer. That all for connectors problem!

Sounds good, combining injector into the driver.
I still don't know why we need to calculate dac_type or tmds_type
dacA, dacB correspond to different registers, thus it must be treat differently, reflected in callback initialization codes. So do tmds types.
Link to comment
Share on other sites

Great progress!!

 

Right now I am using ATIInject.kext plus an older ATINDRV.kext to get full qe/ci and resolution change on my laptop and external monitor. The only thing is the external monitor will not properly go to sleep as it thinks it's always connected, and "detect displays" will freeze the whole system. Would there be a possiblity that in the future, using your framebuffer this problem might be solved?

Link to comment
Share on other sites

Would this project have any effect on the ATI x200/x1150 graphics card?

I hope YES.

 

I make one more test. I connect outer LCD monitor Samsung 740b through VGA connector. My laptop has no DVI connector.

BIOS_4_SCRATCH=03000006 exactly as CRT monitor :D

One difference in 0x5c=0xA or 0xE. These bits is not defined. (CRTC_STATUS).

Other difference (0x60)=0x300. No DDC connect?

Link to comment
Share on other sites

 Share

×
×
  • Create New...