2 * Copyright 2011 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "nouveau_drv.h"
27 #include "nouveau_connector.h"
28 #include "nouveau_encoder.h"
29 #include "nouveau_crtc.h"
32 hdmi_sor(struct drm_encoder
*encoder
)
34 struct drm_nouveau_private
*dev_priv
= encoder
->dev
->dev_private
;
35 if (dev_priv
->chipset
< 0xa3)
41 hdmi_base(struct drm_encoder
*encoder
)
43 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
44 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(nv_encoder
->crtc
);
45 if (!hdmi_sor(encoder
))
46 return 0x616500 + (nv_crtc
->index
* 0x800);
47 return 0x61c500 + (nv_encoder
->or * 0x800);
51 hdmi_wr32(struct drm_encoder
*encoder
, u32 reg
, u32 val
)
53 nv_wr32(encoder
->dev
, hdmi_base(encoder
) + reg
, val
);
57 hdmi_rd32(struct drm_encoder
*encoder
, u32 reg
)
59 return nv_rd32(encoder
->dev
, hdmi_base(encoder
) + reg
);
63 hdmi_mask(struct drm_encoder
*encoder
, u32 reg
, u32 mask
, u32 val
)
65 u32 tmp
= hdmi_rd32(encoder
, reg
);
66 hdmi_wr32(encoder
, reg
, (tmp
& ~mask
) | val
);
71 nouveau_audio_disconnect(struct drm_encoder
*encoder
)
73 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
74 struct drm_device
*dev
= encoder
->dev
;
75 u32
or = nv_encoder
->or * 0x800;
77 if (hdmi_sor(encoder
)) {
78 nv_mask(dev
, 0x61c448 + or, 0x00000003, 0x00000000);
83 nouveau_audio_mode_set(struct drm_encoder
*encoder
,
84 struct drm_display_mode
*mode
)
86 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
87 struct nouveau_connector
*nv_connector
;
88 struct drm_device
*dev
= encoder
->dev
;
89 u32
or = nv_encoder
->or * 0x800;
92 nv_connector
= nouveau_encoder_connector_get(nv_encoder
);
93 if (!drm_detect_monitor_audio(nv_connector
->edid
)) {
94 nouveau_audio_disconnect(encoder
);
98 if (hdmi_sor(encoder
)) {
99 nv_mask(dev
, 0x61c448 + or, 0x00000001, 0x00000001);
101 drm_edid_to_eld(&nv_connector
->base
, nv_connector
->edid
);
102 if (nv_connector
->base
.eld
[0]) {
103 u8
*eld
= nv_connector
->base
.eld
;
104 for (i
= 0; i
< eld
[2] * 4; i
++)
105 nv_wr32(dev
, 0x61c440 + or, (i
<< 8) | eld
[i
]);
106 for (i
= eld
[2] * 4; i
< 0x60; i
++)
107 nv_wr32(dev
, 0x61c440 + or, (i
<< 8) | 0x00);
108 nv_mask(dev
, 0x61c448 + or, 0x00000002, 0x00000002);
114 nouveau_hdmi_infoframe(struct drm_encoder
*encoder
, u32 ctrl
, u8
*frame
)
116 /* calculate checksum for the infoframe */
118 for (i
= 0; i
< frame
[2]; i
++)
120 frame
[3] = 256 - sum
;
122 /* disable infoframe, and write header */
123 hdmi_mask(encoder
, ctrl
+ 0x00, 0x00000001, 0x00000000);
124 hdmi_wr32(encoder
, ctrl
+ 0x08, *(u32
*)frame
& 0xffffff);
126 /* register scans tell me the audio infoframe has only one set of
127 * subpack regs, according to tegra (gee nvidia, it'd be nice if we
128 * could get those docs too!), the hdmi block pads out the rest of
129 * the packet on its own.
134 /* write out checksum and data, weird weird 7 byte register pairs */
135 for (i
= 0; i
< frame
[2] + 1; i
+= 7) {
136 u32 rsubpack
= ctrl
+ 0x0c + ((i
/ 7) * 8);
137 u32
*subpack
= (u32
*)&frame
[3 + i
];
138 hdmi_wr32(encoder
, rsubpack
+ 0, subpack
[0]);
139 hdmi_wr32(encoder
, rsubpack
+ 4, subpack
[1] & 0xffffff);
142 /* enable the infoframe */
143 hdmi_mask(encoder
, ctrl
, 0x00000001, 0x00000001);
147 nouveau_hdmi_video_infoframe(struct drm_encoder
*encoder
,
148 struct drm_display_mode
*mode
)
150 const u8 Y
= 0, A
= 0, B
= 0, S
= 0, C
= 0, M
= 0, R
= 0;
151 const u8 ITC
= 0, EC
= 0, Q
= 0, SC
= 0, VIC
= 0, PR
= 0;
152 const u8 bar_top
= 0, bar_bottom
= 0, bar_left
= 0, bar_right
= 0;
155 frame
[0x00] = 0x82; /* AVI infoframe */
156 frame
[0x01] = 0x02; /* version */
157 frame
[0x02] = 0x0d; /* length */
159 frame
[0x04] = (Y
<< 5) | (A
<< 4) | (B
<< 2) | S
;
160 frame
[0x05] = (C
<< 6) | (M
<< 4) | R
;
161 frame
[0x06] = (ITC
<< 7) | (EC
<< 4) | (Q
<< 2) | SC
;
164 frame
[0x09] = bar_top
& 0xff;
165 frame
[0x0a] = bar_top
>> 8;
166 frame
[0x0b] = bar_bottom
& 0xff;
167 frame
[0x0c] = bar_bottom
>> 8;
168 frame
[0x0d] = bar_left
& 0xff;
169 frame
[0x0e] = bar_left
>> 8;
170 frame
[0x0f] = bar_right
& 0xff;
171 frame
[0x10] = bar_right
>> 8;
176 nouveau_hdmi_infoframe(encoder
, 0x020, frame
);
180 nouveau_hdmi_audio_infoframe(struct drm_encoder
*encoder
,
181 struct drm_display_mode
*mode
)
183 const u8 CT
= 0x00, CC
= 0x01, ceaSS
= 0x00, SF
= 0x00, FMT
= 0x00;
184 const u8 CA
= 0x00, DM_INH
= 0, LSV
= 0x00;
187 frame
[0x00] = 0x84; /* Audio infoframe */
188 frame
[0x01] = 0x01; /* version */
189 frame
[0x02] = 0x0a; /* length */
191 frame
[0x04] = (CT
<< 4) | CC
;
192 frame
[0x05] = (SF
<< 2) | ceaSS
;
195 frame
[0x08] = (DM_INH
<< 7) | (LSV
<< 3);
200 nouveau_hdmi_infoframe(encoder
, 0x000, frame
);
204 nouveau_hdmi_disconnect(struct drm_encoder
*encoder
)
206 nouveau_audio_disconnect(encoder
);
208 /* disable audio and avi infoframes */
209 hdmi_mask(encoder
, 0x000, 0x00000001, 0x00000000);
210 hdmi_mask(encoder
, 0x020, 0x00000001, 0x00000000);
213 hdmi_mask(encoder
, 0x0a4, 0x40000000, 0x00000000);
217 nouveau_hdmi_mode_set(struct drm_encoder
*encoder
,
218 struct drm_display_mode
*mode
)
220 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
221 struct nouveau_connector
*nv_connector
;
222 struct drm_device
*dev
= encoder
->dev
;
223 u32 max_ac_packet
, rekey
;
225 nv_connector
= nouveau_encoder_connector_get(nv_encoder
);
226 if (!mode
|| !nv_connector
|| !nv_connector
->edid
||
227 !drm_detect_hdmi_monitor(nv_connector
->edid
)) {
228 nouveau_hdmi_disconnect(encoder
);
232 nouveau_hdmi_video_infoframe(encoder
, mode
);
233 nouveau_hdmi_audio_infoframe(encoder
, mode
);
235 hdmi_mask(encoder
, 0x0d0, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
236 hdmi_mask(encoder
, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
237 hdmi_mask(encoder
, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
239 nv_mask(dev
, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
240 nv_mask(dev
, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
241 nv_mask(dev
, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
243 /* value matches nvidia binary driver, and tegra constant */
246 max_ac_packet
= mode
->htotal
- mode
->hdisplay
;
247 max_ac_packet
-= rekey
;
248 max_ac_packet
-= 18; /* constant from tegra */
252 hdmi_mask(encoder
, 0x0a4, 0x5f1f003f, 0x40000000 | /* enable */
253 0x1f000000 | /* unknown */
254 max_ac_packet
<< 16 |
257 nouveau_audio_mode_set(encoder
, mode
);