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 ||
36 dev_priv
->chipset
== 0xaa ||
37 dev_priv
->chipset
== 0xac)
43 hdmi_base(struct drm_encoder
*encoder
)
45 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
46 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(nv_encoder
->crtc
);
47 if (!hdmi_sor(encoder
))
48 return 0x616500 + (nv_crtc
->index
* 0x800);
49 return 0x61c500 + (nv_encoder
->or * 0x800);
53 hdmi_wr32(struct drm_encoder
*encoder
, u32 reg
, u32 val
)
55 nv_wr32(encoder
->dev
, hdmi_base(encoder
) + reg
, val
);
59 hdmi_rd32(struct drm_encoder
*encoder
, u32 reg
)
61 return nv_rd32(encoder
->dev
, hdmi_base(encoder
) + reg
);
65 hdmi_mask(struct drm_encoder
*encoder
, u32 reg
, u32 mask
, u32 val
)
67 u32 tmp
= hdmi_rd32(encoder
, reg
);
68 hdmi_wr32(encoder
, reg
, (tmp
& ~mask
) | val
);
73 nouveau_audio_disconnect(struct drm_encoder
*encoder
)
75 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
76 struct drm_device
*dev
= encoder
->dev
;
77 u32
or = nv_encoder
->or * 0x800;
79 if (hdmi_sor(encoder
)) {
80 nv_mask(dev
, 0x61c448 + or, 0x00000003, 0x00000000);
85 nouveau_audio_mode_set(struct drm_encoder
*encoder
,
86 struct drm_display_mode
*mode
)
88 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
89 struct nouveau_connector
*nv_connector
;
90 struct drm_device
*dev
= encoder
->dev
;
91 u32
or = nv_encoder
->or * 0x800;
94 nv_connector
= nouveau_encoder_connector_get(nv_encoder
);
95 if (!drm_detect_monitor_audio(nv_connector
->edid
)) {
96 nouveau_audio_disconnect(encoder
);
100 if (hdmi_sor(encoder
)) {
101 nv_mask(dev
, 0x61c448 + or, 0x00000001, 0x00000001);
103 drm_edid_to_eld(&nv_connector
->base
, nv_connector
->edid
);
104 if (nv_connector
->base
.eld
[0]) {
105 u8
*eld
= nv_connector
->base
.eld
;
106 for (i
= 0; i
< eld
[2] * 4; i
++)
107 nv_wr32(dev
, 0x61c440 + or, (i
<< 8) | eld
[i
]);
108 for (i
= eld
[2] * 4; i
< 0x60; i
++)
109 nv_wr32(dev
, 0x61c440 + or, (i
<< 8) | 0x00);
110 nv_mask(dev
, 0x61c448 + or, 0x00000002, 0x00000002);
116 nouveau_hdmi_infoframe(struct drm_encoder
*encoder
, u32 ctrl
, u8
*frame
)
118 /* calculate checksum for the infoframe */
120 for (i
= 0; i
< frame
[2]; i
++)
122 frame
[3] = 256 - sum
;
124 /* disable infoframe, and write header */
125 hdmi_mask(encoder
, ctrl
+ 0x00, 0x00000001, 0x00000000);
126 hdmi_wr32(encoder
, ctrl
+ 0x08, *(u32
*)frame
& 0xffffff);
128 /* register scans tell me the audio infoframe has only one set of
129 * subpack regs, according to tegra (gee nvidia, it'd be nice if we
130 * could get those docs too!), the hdmi block pads out the rest of
131 * the packet on its own.
136 /* write out checksum and data, weird weird 7 byte register pairs */
137 for (i
= 0; i
< frame
[2] + 1; i
+= 7) {
138 u32 rsubpack
= ctrl
+ 0x0c + ((i
/ 7) * 8);
139 u32
*subpack
= (u32
*)&frame
[3 + i
];
140 hdmi_wr32(encoder
, rsubpack
+ 0, subpack
[0]);
141 hdmi_wr32(encoder
, rsubpack
+ 4, subpack
[1] & 0xffffff);
144 /* enable the infoframe */
145 hdmi_mask(encoder
, ctrl
, 0x00000001, 0x00000001);
149 nouveau_hdmi_video_infoframe(struct drm_encoder
*encoder
,
150 struct drm_display_mode
*mode
)
152 const u8 Y
= 0, A
= 0, B
= 0, S
= 0, C
= 0, M
= 0, R
= 0;
153 const u8 ITC
= 0, EC
= 0, Q
= 0, SC
= 0, VIC
= 0, PR
= 0;
154 const u8 bar_top
= 0, bar_bottom
= 0, bar_left
= 0, bar_right
= 0;
157 frame
[0x00] = 0x82; /* AVI infoframe */
158 frame
[0x01] = 0x02; /* version */
159 frame
[0x02] = 0x0d; /* length */
161 frame
[0x04] = (Y
<< 5) | (A
<< 4) | (B
<< 2) | S
;
162 frame
[0x05] = (C
<< 6) | (M
<< 4) | R
;
163 frame
[0x06] = (ITC
<< 7) | (EC
<< 4) | (Q
<< 2) | SC
;
166 frame
[0x09] = bar_top
& 0xff;
167 frame
[0x0a] = bar_top
>> 8;
168 frame
[0x0b] = bar_bottom
& 0xff;
169 frame
[0x0c] = bar_bottom
>> 8;
170 frame
[0x0d] = bar_left
& 0xff;
171 frame
[0x0e] = bar_left
>> 8;
172 frame
[0x0f] = bar_right
& 0xff;
173 frame
[0x10] = bar_right
>> 8;
178 nouveau_hdmi_infoframe(encoder
, 0x020, frame
);
182 nouveau_hdmi_audio_infoframe(struct drm_encoder
*encoder
,
183 struct drm_display_mode
*mode
)
185 const u8 CT
= 0x00, CC
= 0x01, ceaSS
= 0x00, SF
= 0x00, FMT
= 0x00;
186 const u8 CA
= 0x00, DM_INH
= 0, LSV
= 0x00;
189 frame
[0x00] = 0x84; /* Audio infoframe */
190 frame
[0x01] = 0x01; /* version */
191 frame
[0x02] = 0x0a; /* length */
193 frame
[0x04] = (CT
<< 4) | CC
;
194 frame
[0x05] = (SF
<< 2) | ceaSS
;
197 frame
[0x08] = (DM_INH
<< 7) | (LSV
<< 3);
202 nouveau_hdmi_infoframe(encoder
, 0x000, frame
);
206 nouveau_hdmi_disconnect(struct drm_encoder
*encoder
)
208 nouveau_audio_disconnect(encoder
);
210 /* disable audio and avi infoframes */
211 hdmi_mask(encoder
, 0x000, 0x00000001, 0x00000000);
212 hdmi_mask(encoder
, 0x020, 0x00000001, 0x00000000);
215 hdmi_mask(encoder
, 0x0a4, 0x40000000, 0x00000000);
219 nouveau_hdmi_mode_set(struct drm_encoder
*encoder
,
220 struct drm_display_mode
*mode
)
222 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
223 struct nouveau_connector
*nv_connector
;
224 struct drm_device
*dev
= encoder
->dev
;
225 u32 max_ac_packet
, rekey
;
227 nv_connector
= nouveau_encoder_connector_get(nv_encoder
);
228 if (!mode
|| !nv_connector
|| !nv_connector
->edid
||
229 !drm_detect_hdmi_monitor(nv_connector
->edid
)) {
230 nouveau_hdmi_disconnect(encoder
);
234 nouveau_hdmi_video_infoframe(encoder
, mode
);
235 nouveau_hdmi_audio_infoframe(encoder
, mode
);
237 hdmi_mask(encoder
, 0x0d0, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
238 hdmi_mask(encoder
, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
239 hdmi_mask(encoder
, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
241 nv_mask(dev
, 0x61733c, 0x00100000, 0x00100000); /* RESETF */
242 nv_mask(dev
, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */
243 nv_mask(dev
, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */
245 /* value matches nvidia binary driver, and tegra constant */
248 max_ac_packet
= mode
->htotal
- mode
->hdisplay
;
249 max_ac_packet
-= rekey
;
250 max_ac_packet
-= 18; /* constant from tegra */
254 hdmi_mask(encoder
, 0x0a4, 0x5f1f003f, 0x40000000 | /* enable */
255 0x1f000000 | /* unknown */
256 max_ac_packet
<< 16 |
259 nouveau_audio_mode_set(encoder
, mode
);