2 * Copyright (C) 2009 Francisco Jerez.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "nouveau_drm.h"
29 #include "nouveau_reg.h"
30 #include "nouveau_encoder.h"
31 #include "nouveau_connector.h"
32 #include "nouveau_crtc.h"
33 #include "nouveau_hw.h"
34 #include "drm_crtc_helper.h"
36 #include "i2c/ch7006.h"
38 #include <subdev/i2c.h>
40 static struct i2c_board_info nv04_tv_encoder_info
[] = {
42 I2C_BOARD_INFO("ch7006", 0x75),
43 .platform_data
= &(struct ch7006_encoder_params
) {
44 CH7006_FORMAT_RGB24m12I
, CH7006_CLOCK_MASTER
,
46 CH7006_SYNC_SLAVE
, CH7006_SYNC_SEPARATED
,
47 CH7006_POUT_3_3V
, CH7006_ACTIVE_HSYNC
53 int nv04_tv_identify(struct drm_device
*dev
, int i2c_index
)
55 struct nouveau_drm
*drm
= nouveau_drm(dev
);
56 struct nouveau_i2c
*i2c
= nouveau_i2c(drm
->device
);
58 return i2c
->identify(i2c
, i2c_index
, "TV encoder",
59 nv04_tv_encoder_info
, NULL
);
63 #define PLLSEL_TV_CRTC1_MASK \
64 (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1 \
65 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
66 #define PLLSEL_TV_CRTC2_MASK \
67 (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK2 \
68 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK2)
70 static void nv04_tv_dpms(struct drm_encoder
*encoder
, int mode
)
72 struct drm_device
*dev
= encoder
->dev
;
73 struct nouveau_drm
*drm
= nouveau_drm(dev
);
74 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
75 struct nv04_mode_state
*state
= &nv04_display(dev
)->mode_reg
;
78 NV_INFO(drm
, "Setting dpms mode %d on TV encoder (output %d)\n",
79 mode
, nv_encoder
->dcb
->index
);
81 state
->pllsel
&= ~(PLLSEL_TV_CRTC1_MASK
| PLLSEL_TV_CRTC2_MASK
);
83 if (mode
== DRM_MODE_DPMS_ON
) {
84 int head
= nouveau_crtc(encoder
->crtc
)->index
;
85 crtc1A
= NVReadVgaCrtc(dev
, head
, NV_CIO_CRE_RPC1_INDEX
);
87 state
->pllsel
|= head
? PLLSEL_TV_CRTC2_MASK
:
93 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_RPC1_INDEX
, crtc1A
);
96 NVWriteRAMDAC(dev
, 0, NV_PRAMDAC_PLL_COEFF_SELECT
, state
->pllsel
);
98 get_slave_funcs(encoder
)->dpms(encoder
, mode
);
101 static void nv04_tv_bind(struct drm_device
*dev
, int head
, bool bind
)
103 struct nv04_crtc_reg
*state
= &nv04_display(dev
)->mode_reg
.crtc_reg
[head
];
108 state
->CRTC
[NV_CIO_CRE_49
] |= 0x10;
110 state
->CRTC
[NV_CIO_CRE_49
] &= ~0x10;
112 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_LCD__INDEX
,
113 state
->CRTC
[NV_CIO_CRE_LCD__INDEX
]);
114 NVWriteVgaCrtc(dev
, head
, NV_CIO_CRE_49
,
115 state
->CRTC
[NV_CIO_CRE_49
]);
116 NVWriteRAMDAC(dev
, head
, NV_PRAMDAC_TV_SETUP
,
120 static void nv04_tv_prepare(struct drm_encoder
*encoder
)
122 struct drm_device
*dev
= encoder
->dev
;
123 int head
= nouveau_crtc(encoder
->crtc
)->index
;
124 struct drm_encoder_helper_funcs
*helper
= encoder
->helper_private
;
126 helper
->dpms(encoder
, DRM_MODE_DPMS_OFF
);
128 nv04_dfp_disable(dev
, head
);
130 if (nv_two_heads(dev
))
131 nv04_tv_bind(dev
, head
^ 1, false);
133 nv04_tv_bind(dev
, head
, true);
136 static void nv04_tv_mode_set(struct drm_encoder
*encoder
,
137 struct drm_display_mode
*mode
,
138 struct drm_display_mode
*adjusted_mode
)
140 struct drm_device
*dev
= encoder
->dev
;
141 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(encoder
->crtc
);
142 struct nv04_crtc_reg
*regp
= &nv04_display(dev
)->mode_reg
.crtc_reg
[nv_crtc
->index
];
144 regp
->tv_htotal
= adjusted_mode
->htotal
;
145 regp
->tv_vtotal
= adjusted_mode
->vtotal
;
147 /* These delay the TV signals with respect to the VGA port,
148 * they might be useful if we ever allow a CRTC to drive
152 regp
->tv_hsync_delay
= 1;
153 regp
->tv_hsync_delay2
= 64;
155 regp
->tv_vsync_delay
= 1;
157 get_slave_funcs(encoder
)->mode_set(encoder
, mode
, adjusted_mode
);
160 static void nv04_tv_commit(struct drm_encoder
*encoder
)
162 struct nouveau_encoder
*nv_encoder
= nouveau_encoder(encoder
);
163 struct drm_device
*dev
= encoder
->dev
;
164 struct nouveau_drm
*drm
= nouveau_drm(dev
);
165 struct nouveau_crtc
*nv_crtc
= nouveau_crtc(encoder
->crtc
);
166 struct drm_encoder_helper_funcs
*helper
= encoder
->helper_private
;
168 helper
->dpms(encoder
, DRM_MODE_DPMS_ON
);
170 NV_INFO(drm
, "Output %s is running on CRTC %d using output %c\n",
171 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder
)->base
), nv_crtc
->index
,
172 '@' + ffs(nv_encoder
->dcb
->or));
175 static void nv04_tv_destroy(struct drm_encoder
*encoder
)
177 get_slave_funcs(encoder
)->destroy(encoder
);
178 drm_encoder_cleanup(encoder
);
180 kfree(encoder
->helper_private
);
181 kfree(nouveau_encoder(encoder
));
184 static const struct drm_encoder_funcs nv04_tv_funcs
= {
185 .destroy
= nv04_tv_destroy
,
189 nv04_tv_create(struct drm_connector
*connector
, struct dcb_output
*entry
)
191 struct nouveau_encoder
*nv_encoder
;
192 struct drm_encoder
*encoder
;
193 struct drm_device
*dev
= connector
->dev
;
194 struct drm_encoder_helper_funcs
*hfuncs
;
195 struct drm_encoder_slave_funcs
*sfuncs
;
196 struct nouveau_drm
*drm
= nouveau_drm(dev
);
197 struct nouveau_i2c
*i2c
= nouveau_i2c(drm
->device
);
198 struct nouveau_i2c_port
*port
= i2c
->find(i2c
, entry
->i2c_index
);
201 /* Ensure that we can talk to this encoder */
202 type
= nv04_tv_identify(dev
, entry
->i2c_index
);
206 /* Allocate the necessary memory */
207 nv_encoder
= kzalloc(sizeof(*nv_encoder
), GFP_KERNEL
);
211 hfuncs
= kzalloc(sizeof(*hfuncs
), GFP_KERNEL
);
217 /* Initialize the common members */
218 encoder
= to_drm_encoder(nv_encoder
);
220 drm_encoder_init(dev
, encoder
, &nv04_tv_funcs
, DRM_MODE_ENCODER_TVDAC
);
221 drm_encoder_helper_add(encoder
, hfuncs
);
223 encoder
->possible_crtcs
= entry
->heads
;
224 encoder
->possible_clones
= 0;
225 nv_encoder
->dcb
= entry
;
226 nv_encoder
->or = ffs(entry
->or) - 1;
228 /* Run the slave-specific initialization */
229 ret
= drm_i2c_encoder_init(dev
, to_encoder_slave(encoder
),
230 &port
->adapter
, &nv04_tv_encoder_info
[type
]);
234 /* Fill the function pointers */
235 sfuncs
= get_slave_funcs(encoder
);
237 *hfuncs
= (struct drm_encoder_helper_funcs
) {
238 .dpms
= nv04_tv_dpms
,
239 .save
= sfuncs
->save
,
240 .restore
= sfuncs
->restore
,
241 .mode_fixup
= sfuncs
->mode_fixup
,
242 .prepare
= nv04_tv_prepare
,
243 .commit
= nv04_tv_commit
,
244 .mode_set
= nv04_tv_mode_set
,
245 .detect
= sfuncs
->detect
,
248 /* Attach it to the specified connector. */
249 sfuncs
->create_resources(encoder
, connector
);
250 drm_mode_connector_attach_encoder(connector
, encoder
);
255 drm_encoder_cleanup(encoder
);