2 * Copyright 2007 Jérôme Glisse
3 * Copyright 2007 Alex Deucher
4 * Copyright 2007 Dave Airlie
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation on the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial
17 * portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
28 #include "radeon_ms.h"
30 static int get_clock(void *data)
32 struct radeon_ms_i2c *i2c = data;
33 struct drm_radeon_private *dev_priv = i2c->drm_dev->dev_private;
39 if ((REG_G(VIPPAD_Y, VIPPAD_Y_VHAD, v) & 2)) {
46 v = MMIO_R(VIPPAD1_Y);
47 if ((REG_G(VIPPAD1_Y, VIPPAD_Y_DVODATA, v) & 8)) {
54 v = MMIO_R(GPIO_DDC1);
55 if ((GPIO_DDC1__DDC1_CLK_INPUT & v)) {
62 v = MMIO_R(GPIO_DDC2);
63 if ((GPIO_DDC2__DDC2_CLK_INPUT & v)) {
70 v = MMIO_R(GPIO_MONID);
71 if ((GPIO_MONID__GPIO_MONID_1_INPUT & v)) {
78 v = MMIO_R(GPIO_CRT2_DDC);
79 if ((GPIO_CRT2_DDC__CRT2_DDC_CLK_INPUT & v)) {
92 static int get_data(void *data)
94 struct radeon_ms_i2c *i2c = data;
95 struct drm_radeon_private *dev_priv = i2c->drm_dev->dev_private;
100 v = MMIO_R(VIPPAD_Y);
101 if ((REG_G(VIPPAD_Y, VIPPAD_Y_VHAD, v) & 1)) {
108 v = MMIO_R(VIPPAD1_Y);
109 if ((REG_G(VIPPAD1_Y, VIPPAD_Y_DVODATA, v) & 4)) {
116 v = MMIO_R(GPIO_DDC1);
117 if ((GPIO_DDC1__DDC1_DATA_INPUT & v)) {
124 v = MMIO_R(GPIO_DDC2);
125 if ((GPIO_DDC2__DDC2_DATA_INPUT & v)) {
132 v = MMIO_R(GPIO_MONID);
133 if ((GPIO_MONID__GPIO_MONID_0_INPUT & v)) {
140 v = MMIO_R(GPIO_CRT2_DDC);
141 if ((GPIO_CRT2_DDC__CRT2_DDC_DATA_INPUT & v)) {
154 static void set_clock(void *i2c_priv, int clock)
156 struct radeon_ms_i2c *i2c = i2c_priv;
157 struct drm_radeon_private *dev_priv = i2c->drm_dev->dev_private;
160 v = MMIO_R(i2c->reg);
163 line = REG_G(VIPPAD_EN, VIPPAD_EN_VHAD, v) & ~2;
164 v &= ~VIPPAD_EN__VIPPAD_EN_VHAD__MASK;
166 v |= REG_S(VIPPAD_EN, VIPPAD_EN_VHAD, line | 2);
168 v |= REG_S(VIPPAD_EN, VIPPAD_EN_VHAD, line);
172 line = REG_G(VIPPAD1_EN, VIPPAD_EN_DVODATA, v) & ~8;
173 v &= ~VIPPAD1_EN__VIPPAD_EN_DVODATA__MASK;
175 v |= REG_S(VIPPAD1_EN, VIPPAD_EN_DVODATA, line | 8);
177 v |= REG_S(VIPPAD1_EN, VIPPAD_EN_DVODATA, line);
181 v &= ~GPIO_DDC1__DDC1_CLK_OUT_EN;
183 v |= GPIO_DDC1__DDC1_CLK_OUT_EN;
187 v &= ~GPIO_DDC2__DDC2_CLK_OUT_EN;
189 v |= GPIO_DDC2__DDC2_CLK_OUT_EN;
193 v &= ~GPIO_MONID__GPIO_MONID_1_OUT_EN;
195 v |= GPIO_MONID__GPIO_MONID_1_OUT_EN;
199 v &= ~GPIO_CRT2_DDC__CRT2_DDC_CLK_OUT_EN;
201 v |= GPIO_CRT2_DDC__CRT2_DDC_CLK_OUT_EN;
210 static void set_data(void *i2c_priv, int data)
212 struct radeon_ms_i2c *i2c = i2c_priv;
213 struct drm_radeon_private *dev_priv = i2c->drm_dev->dev_private;
216 v = MMIO_R(i2c->reg);
219 line = REG_G(VIPPAD_EN, VIPPAD_EN_VHAD, v) & ~1;
220 v &= ~VIPPAD_EN__VIPPAD_EN_VHAD__MASK;
222 v |= REG_S(VIPPAD_EN, VIPPAD_EN_VHAD, line | 1);
224 v |= REG_S(VIPPAD_EN, VIPPAD_EN_VHAD, line);
228 line = REG_G(VIPPAD1_EN, VIPPAD_EN_DVODATA, v) & ~4;
229 v &= ~VIPPAD1_EN__VIPPAD_EN_DVODATA__MASK;
231 v |= REG_S(VIPPAD1_EN, VIPPAD_EN_DVODATA, line | 4);
233 v |= REG_S(VIPPAD1_EN, VIPPAD_EN_DVODATA, line);
237 v &= ~GPIO_DDC1__DDC1_DATA_OUT_EN;
239 v |= GPIO_DDC1__DDC1_DATA_OUT_EN;
243 v &= ~GPIO_DDC2__DDC2_DATA_OUT_EN;
245 v |= GPIO_DDC2__DDC2_DATA_OUT_EN;
249 v &= ~GPIO_MONID__GPIO_MONID_0_OUT_EN;
251 v |= GPIO_MONID__GPIO_MONID_0_OUT_EN;
255 v &= ~GPIO_CRT2_DDC__CRT2_DDC_DATA_OUT_EN;
257 v |= GPIO_CRT2_DDC__CRT2_DDC_DATA_OUT_EN;
267 * radeon_ms_i2c_create - instantiate an radeon i2c bus on specified GPIO reg
269 * @output: driver specific output device
270 * @reg: GPIO reg to use
271 * @name: name for this bus
273 * Creates and registers a new i2c bus with the Linux i2c layer, for use
274 * in output probing and control (e.g. DDC or SDVO control functions).
277 struct radeon_ms_i2c *radeon_ms_i2c_create(struct drm_device *dev,
281 struct radeon_ms_i2c *i2c;
284 i2c = drm_alloc(sizeof(struct radeon_ms_i2c), DRM_MEM_DRIVER);
288 memset(i2c, 0, sizeof(struct radeon_ms_i2c));
292 snprintf(i2c->adapter.name, I2C_NAME_SIZE, "radeon-%s", name);
293 i2c->adapter.owner = THIS_MODULE;
294 /* fixme need to take a look at what its needed for */
295 i2c->adapter.id = I2C_HW_B_RADEON;
296 i2c->adapter.algo_data = &i2c->algo;
297 i2c->adapter.dev.parent = &dev->pdev->dev;
298 i2c->algo.setsda = set_data;
299 i2c->algo.setscl = set_clock;
300 i2c->algo.getsda = get_data;
301 i2c->algo.getscl = get_clock;
302 i2c->algo.udelay = 20;
303 i2c->algo.timeout = usecs_to_jiffies(2200);
304 i2c->algo.data = i2c;
306 i2c_set_adapdata(&i2c->adapter, i2c);
308 ret = i2c_bit_add_bus(&i2c->adapter);
310 DRM_INFO("[radeon_ms] failed to register I2C '%s' bus (0x%X)\n",
311 i2c->adapter.name, reg);
314 DRM_INFO("[radeon_ms] registered I2C '%s' bus (0x%X)\n",
315 i2c->adapter.name, reg);
319 drm_free(i2c, sizeof(struct radeon_ms_i2c), DRM_MEM_DRIVER);
324 * radeon_ms_i2c_destroy - unregister and free i2c bus resources
325 * @output: channel to free
327 * Unregister the adapter from the i2c layer, then free the structure.
329 void radeon_ms_i2c_destroy(struct radeon_ms_i2c *i2c)
334 i2c_del_adapter(&i2c->adapter);
335 drm_free(i2c, sizeof(struct radeon_ms_i2c), DRM_MEM_DRIVER);