1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2007-8 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell *
5254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
6254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
7254885Sdumbbell * to deal in the Software without restriction, including without limitation
8254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
10254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
11254885Sdumbbell *
12254885Sdumbbell * The above copyright notice and this permission notice shall be included in
13254885Sdumbbell * all copies or substantial portions of the Software.
14254885Sdumbbell *
15254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
22254885Sdumbbell *
23254885Sdumbbell * Authors: Dave Airlie
24254885Sdumbbell *          Alex Deucher
25254885Sdumbbell */
26254885Sdumbbell
27254885Sdumbbell#include <sys/cdefs.h>
28254885Sdumbbell__FBSDID("$FreeBSD$");
29254885Sdumbbell
30254885Sdumbbell#include <dev/drm2/drmP.h>
31254885Sdumbbell#include <dev/drm2/drm_edid.h>
32254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
33254885Sdumbbell#include <dev/iicbus/iic.h>
34254885Sdumbbell#include <dev/iicbus/iiconf.h>
35254885Sdumbbell#include <dev/iicbus/iicbus.h>
36254885Sdumbbell#include "radeon.h"
37254885Sdumbbell#include "atom.h"
38254885Sdumbbell#include "iicbus_if.h"
39254885Sdumbbell#include "iicbb_if.h"
40254885Sdumbbell
41254885Sdumbbell/**
42254885Sdumbbell * radeon_ddc_probe
43254885Sdumbbell *
44254885Sdumbbell */
45254885Sdumbbellbool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux)
46254885Sdumbbell{
47254885Sdumbbell	u8 out = 0x0;
48254885Sdumbbell	u8 buf[8];
49254885Sdumbbell	int ret;
50254885Sdumbbell	struct iic_msg msgs[] = {
51254885Sdumbbell		{
52254885Sdumbbell			.slave = DDC_ADDR << 1,
53254885Sdumbbell			.flags = 0,
54254885Sdumbbell			.len = 1,
55254885Sdumbbell			.buf = &out,
56254885Sdumbbell		},
57254885Sdumbbell		{
58254885Sdumbbell			.slave = DDC_ADDR << 1,
59254885Sdumbbell			.flags = IIC_M_RD,
60254885Sdumbbell			.len = 8,
61254885Sdumbbell			.buf = buf,
62254885Sdumbbell		}
63254885Sdumbbell	};
64254885Sdumbbell
65254885Sdumbbell	/* on hw with routers, select right port */
66254885Sdumbbell	if (radeon_connector->router.ddc_valid)
67254885Sdumbbell		radeon_router_select_ddc_port(radeon_connector);
68254885Sdumbbell
69254885Sdumbbell	if (use_aux) {
70254885Sdumbbell		struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
71254885Sdumbbell		ret = iicbus_transfer(dig->dp_i2c_bus->adapter, msgs, 2);
72254885Sdumbbell	} else {
73254885Sdumbbell		ret = iicbus_transfer(radeon_connector->ddc_bus->adapter, msgs, 2);
74254885Sdumbbell	}
75254885Sdumbbell
76254885Sdumbbell	if (ret != 0)
77254885Sdumbbell		/* Couldn't find an accessible DDC on this connector */
78254885Sdumbbell		return false;
79254885Sdumbbell	/* Probe also for valid EDID header
80254885Sdumbbell	 * EDID header starts with:
81254885Sdumbbell	 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
82254885Sdumbbell	 * Only the first 6 bytes must be valid as
83254885Sdumbbell	 * drm_edid_block_valid() can fix the last 2 bytes */
84254885Sdumbbell	if (drm_edid_header_is_valid(buf) < 6) {
85254885Sdumbbell		/* Couldn't find an accessible EDID on this
86254885Sdumbbell		 * connector */
87254885Sdumbbell		return false;
88254885Sdumbbell	}
89254885Sdumbbell	return true;
90254885Sdumbbell}
91254885Sdumbbell
92254885Sdumbbell/* bit banging i2c */
93254885Sdumbbell
94254885Sdumbbellstatic int radeon_iicbb_pre_xfer(device_t dev)
95254885Sdumbbell{
96254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
97254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
98254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
99254885Sdumbbell	uint32_t temp;
100254885Sdumbbell
101254885Sdumbbell	/* RV410 appears to have a bug where the hw i2c in reset
102254885Sdumbbell	 * holds the i2c port in a bad state - switch hw i2c away before
103254885Sdumbbell	 * doing DDC - do this for all r200s/r300s/r400s for safety sake
104254885Sdumbbell	 */
105254885Sdumbbell	if (rec->hw_capable) {
106254885Sdumbbell		if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) {
107254885Sdumbbell			u32 reg;
108254885Sdumbbell
109254885Sdumbbell			if (rdev->family >= CHIP_RV350)
110254885Sdumbbell				reg = RADEON_GPIO_MONID;
111254885Sdumbbell			else if ((rdev->family == CHIP_R300) ||
112254885Sdumbbell				 (rdev->family == CHIP_R350))
113254885Sdumbbell				reg = RADEON_GPIO_DVI_DDC;
114254885Sdumbbell			else
115254885Sdumbbell				reg = RADEON_GPIO_CRT2_DDC;
116254885Sdumbbell
117254885Sdumbbell			sx_xlock(&rdev->dc_hw_i2c_mutex);
118254885Sdumbbell			if (rec->a_clk_reg == reg) {
119254885Sdumbbell				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
120254885Sdumbbell							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1)));
121254885Sdumbbell			} else {
122254885Sdumbbell				WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST |
123254885Sdumbbell							       R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
124254885Sdumbbell			}
125254885Sdumbbell			sx_xunlock(&rdev->dc_hw_i2c_mutex);
126254885Sdumbbell		}
127254885Sdumbbell	}
128254885Sdumbbell
129254885Sdumbbell	/* switch the pads to ddc mode */
130254885Sdumbbell	if (ASIC_IS_DCE3(rdev) && rec->hw_capable) {
131254885Sdumbbell		temp = RREG32(rec->mask_clk_reg);
132254885Sdumbbell		temp &= ~(1 << 16);
133254885Sdumbbell		WREG32(rec->mask_clk_reg, temp);
134254885Sdumbbell	}
135254885Sdumbbell
136254885Sdumbbell	/* clear the output pin values */
137254885Sdumbbell	temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask;
138254885Sdumbbell	WREG32(rec->a_clk_reg, temp);
139254885Sdumbbell
140254885Sdumbbell	temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask;
141254885Sdumbbell	WREG32(rec->a_data_reg, temp);
142254885Sdumbbell
143254885Sdumbbell	/* set the pins to input */
144254885Sdumbbell	temp = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
145254885Sdumbbell	WREG32(rec->en_clk_reg, temp);
146254885Sdumbbell
147254885Sdumbbell	temp = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
148254885Sdumbbell	WREG32(rec->en_data_reg, temp);
149254885Sdumbbell
150254885Sdumbbell	/* mask the gpio pins for software use */
151254885Sdumbbell	temp = RREG32(rec->mask_clk_reg) | rec->mask_clk_mask;
152254885Sdumbbell	WREG32(rec->mask_clk_reg, temp);
153254885Sdumbbell	temp = RREG32(rec->mask_clk_reg);
154254885Sdumbbell
155254885Sdumbbell	temp = RREG32(rec->mask_data_reg) | rec->mask_data_mask;
156254885Sdumbbell	WREG32(rec->mask_data_reg, temp);
157254885Sdumbbell	temp = RREG32(rec->mask_data_reg);
158254885Sdumbbell
159254885Sdumbbell	return 0;
160254885Sdumbbell}
161254885Sdumbbell
162254885Sdumbbellstatic void radeon_iicbb_post_xfer(device_t dev)
163254885Sdumbbell{
164254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
165254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
166254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
167254885Sdumbbell	uint32_t temp;
168254885Sdumbbell
169254885Sdumbbell	/* unmask the gpio pins for software use */
170254885Sdumbbell	temp = RREG32(rec->mask_clk_reg) & ~rec->mask_clk_mask;
171254885Sdumbbell	WREG32(rec->mask_clk_reg, temp);
172254885Sdumbbell	temp = RREG32(rec->mask_clk_reg);
173254885Sdumbbell
174254885Sdumbbell	temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask;
175254885Sdumbbell	WREG32(rec->mask_data_reg, temp);
176254885Sdumbbell	temp = RREG32(rec->mask_data_reg);
177254885Sdumbbell}
178254885Sdumbbell
179254885Sdumbbellstatic int radeon_iicbb_get_clock(device_t dev)
180254885Sdumbbell{
181254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
182254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
183254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
184254885Sdumbbell	uint32_t val;
185254885Sdumbbell
186254885Sdumbbell	/* read the value off the pin */
187254885Sdumbbell	val = RREG32(rec->y_clk_reg);
188254885Sdumbbell	val &= rec->y_clk_mask;
189254885Sdumbbell
190254885Sdumbbell	return (val != 0);
191254885Sdumbbell}
192254885Sdumbbell
193254885Sdumbbell
194254885Sdumbbellstatic int radeon_iicbb_get_data(device_t dev)
195254885Sdumbbell{
196254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
197254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
198254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
199254885Sdumbbell	uint32_t val;
200254885Sdumbbell
201254885Sdumbbell	/* read the value off the pin */
202254885Sdumbbell	val = RREG32(rec->y_data_reg);
203254885Sdumbbell	val &= rec->y_data_mask;
204254885Sdumbbell
205254885Sdumbbell	return (val != 0);
206254885Sdumbbell}
207254885Sdumbbell
208254885Sdumbbellstatic void radeon_iicbb_set_clock(device_t dev, int clock)
209254885Sdumbbell{
210254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
211254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
212254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
213254885Sdumbbell	uint32_t val;
214254885Sdumbbell
215254885Sdumbbell	/* set pin direction */
216254885Sdumbbell	val = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
217254885Sdumbbell	val |= clock ? 0 : rec->en_clk_mask;
218254885Sdumbbell	WREG32(rec->en_clk_reg, val);
219254885Sdumbbell}
220254885Sdumbbell
221254885Sdumbbellstatic void radeon_iicbb_set_data(device_t dev, int data)
222254885Sdumbbell{
223254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
224254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
225254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
226254885Sdumbbell	uint32_t val;
227254885Sdumbbell
228254885Sdumbbell	/* set pin direction */
229254885Sdumbbell	val = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
230254885Sdumbbell	val |= data ? 0 : rec->en_data_mask;
231254885Sdumbbell	WREG32(rec->en_data_reg, val);
232254885Sdumbbell}
233254885Sdumbbell
234254885Sdumbbellstatic int
235254885Sdumbbellradeon_iicbb_probe(device_t dev)
236254885Sdumbbell{
237254885Sdumbbell
238254885Sdumbbell	return (BUS_PROBE_DEFAULT);
239254885Sdumbbell}
240254885Sdumbbell
241254885Sdumbbellstatic int
242254885Sdumbbellradeon_iicbb_attach(device_t dev)
243254885Sdumbbell{
244254885Sdumbbell	struct radeon_i2c_chan *i2c;
245254885Sdumbbell	device_t iic_dev;
246254885Sdumbbell
247254885Sdumbbell	i2c = device_get_softc(dev);
248254885Sdumbbell	device_set_desc(dev, i2c->name);
249254885Sdumbbell
250254885Sdumbbell	/* add generic bit-banging code */
251254885Sdumbbell	iic_dev = device_add_child(dev, "iicbb", -1);
252254885Sdumbbell	if (iic_dev == NULL)
253254885Sdumbbell		return (ENXIO);
254254885Sdumbbell	device_quiet(iic_dev);
255254885Sdumbbell
256254885Sdumbbell	/* attach and probe added child */
257254885Sdumbbell	bus_generic_attach(dev);
258254885Sdumbbell
259254885Sdumbbell	return (0);
260254885Sdumbbell}
261254885Sdumbbell
262254885Sdumbbellstatic int
263254885Sdumbbellradeon_iicbb_detach(device_t dev)
264254885Sdumbbell{
265254885Sdumbbell
266254885Sdumbbell	/* detach bit-banding code. */
267254885Sdumbbell	bus_generic_detach(dev);
268254885Sdumbbell
269254885Sdumbbell	/* delete bit-banding code. */
270254885Sdumbbell	device_delete_children(dev);
271254885Sdumbbell	return (0);
272254885Sdumbbell}
273254885Sdumbbell
274254885Sdumbbellstatic int
275254885Sdumbbellradeon_iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
276254885Sdumbbell{
277254885Sdumbbell
278254885Sdumbbell	/* Not sure what to do here. */
279254885Sdumbbell	return 0;
280254885Sdumbbell}
281254885Sdumbbell
282254885Sdumbbellstatic device_method_t radeon_iicbb_methods[] =	{
283254885Sdumbbell	DEVMETHOD(device_probe,		radeon_iicbb_probe),
284254885Sdumbbell	DEVMETHOD(device_attach,	radeon_iicbb_attach),
285254885Sdumbbell	DEVMETHOD(device_detach,	radeon_iicbb_detach),
286254885Sdumbbell
287254885Sdumbbell	DEVMETHOD(bus_add_child,	bus_generic_add_child),
288254885Sdumbbell	DEVMETHOD(bus_print_child,	bus_generic_print_child),
289254885Sdumbbell
290254885Sdumbbell	DEVMETHOD(iicbb_reset,		radeon_iicbb_reset),
291254885Sdumbbell	DEVMETHOD(iicbb_pre_xfer,	radeon_iicbb_pre_xfer),
292254885Sdumbbell	DEVMETHOD(iicbb_post_xfer,	radeon_iicbb_post_xfer),
293254885Sdumbbell	DEVMETHOD(iicbb_setsda,		radeon_iicbb_set_data),
294254885Sdumbbell	DEVMETHOD(iicbb_setscl,		radeon_iicbb_set_clock),
295254885Sdumbbell	DEVMETHOD(iicbb_getsda,		radeon_iicbb_get_data),
296254885Sdumbbell	DEVMETHOD(iicbb_getscl,		radeon_iicbb_get_clock),
297254885Sdumbbell	DEVMETHOD_END
298254885Sdumbbell};
299254885Sdumbbell
300254885Sdumbbellstatic driver_t radeon_iicbb_driver = {
301254885Sdumbbell	"radeon_iicbb",
302254885Sdumbbell	radeon_iicbb_methods,
303254885Sdumbbell	0 /* softc will be allocated by parent */
304254885Sdumbbell};
305254885Sdumbbellstatic devclass_t radeon_iicbb_devclass;
306254885SdumbbellDRIVER_MODULE_ORDERED(radeon_iicbb, drmn, radeon_iicbb_driver,
307254885Sdumbbell    radeon_iicbb_devclass, 0, 0, SI_ORDER_FIRST);
308254885SdumbbellDRIVER_MODULE(iicbb, radeon_iicbb, iicbb_driver, iicbb_devclass, 0, 0);
309254885Sdumbbell
310254885Sdumbbell/* hw i2c */
311254885Sdumbbell
312254885Sdumbbellstatic u32 radeon_get_i2c_prescale(struct radeon_device *rdev)
313254885Sdumbbell{
314254885Sdumbbell	u32 sclk = rdev->pm.current_sclk;
315254885Sdumbbell	u32 prescale = 0;
316254885Sdumbbell	u32 nm;
317254885Sdumbbell	u8 n, m, loop;
318254885Sdumbbell	int i2c_clock;
319254885Sdumbbell
320254885Sdumbbell	switch (rdev->family) {
321254885Sdumbbell	case CHIP_R100:
322254885Sdumbbell	case CHIP_RV100:
323254885Sdumbbell	case CHIP_RS100:
324254885Sdumbbell	case CHIP_RV200:
325254885Sdumbbell	case CHIP_RS200:
326254885Sdumbbell	case CHIP_R200:
327254885Sdumbbell	case CHIP_RV250:
328254885Sdumbbell	case CHIP_RS300:
329254885Sdumbbell	case CHIP_RV280:
330254885Sdumbbell	case CHIP_R300:
331254885Sdumbbell	case CHIP_R350:
332254885Sdumbbell	case CHIP_RV350:
333254885Sdumbbell		i2c_clock = 60;
334254885Sdumbbell		nm = (sclk * 10) / (i2c_clock * 4);
335254885Sdumbbell		for (loop = 1; loop < 255; loop++) {
336254885Sdumbbell			if ((nm / loop) < loop)
337254885Sdumbbell				break;
338254885Sdumbbell		}
339254885Sdumbbell		n = loop - 1;
340254885Sdumbbell		m = loop - 2;
341254885Sdumbbell		prescale = m | (n << 8);
342254885Sdumbbell		break;
343254885Sdumbbell	case CHIP_RV380:
344254885Sdumbbell	case CHIP_RS400:
345254885Sdumbbell	case CHIP_RS480:
346254885Sdumbbell	case CHIP_R420:
347254885Sdumbbell	case CHIP_R423:
348254885Sdumbbell	case CHIP_RV410:
349254885Sdumbbell		prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
350254885Sdumbbell		break;
351254885Sdumbbell	case CHIP_RS600:
352254885Sdumbbell	case CHIP_RS690:
353254885Sdumbbell	case CHIP_RS740:
354254885Sdumbbell		/* todo */
355254885Sdumbbell		break;
356254885Sdumbbell	case CHIP_RV515:
357254885Sdumbbell	case CHIP_R520:
358254885Sdumbbell	case CHIP_RV530:
359254885Sdumbbell	case CHIP_RV560:
360254885Sdumbbell	case CHIP_RV570:
361254885Sdumbbell	case CHIP_R580:
362254885Sdumbbell		i2c_clock = 50;
363254885Sdumbbell		if (rdev->family == CHIP_R520)
364254885Sdumbbell			prescale = (127 << 8) + ((sclk * 10) / (4 * 127 * i2c_clock));
365254885Sdumbbell		else
366254885Sdumbbell			prescale = (((sclk * 10)/(4 * 128 * 100) + 1) << 8) + 128;
367254885Sdumbbell		break;
368254885Sdumbbell	case CHIP_R600:
369254885Sdumbbell	case CHIP_RV610:
370254885Sdumbbell	case CHIP_RV630:
371254885Sdumbbell	case CHIP_RV670:
372254885Sdumbbell		/* todo */
373254885Sdumbbell		break;
374254885Sdumbbell	case CHIP_RV620:
375254885Sdumbbell	case CHIP_RV635:
376254885Sdumbbell	case CHIP_RS780:
377254885Sdumbbell	case CHIP_RS880:
378254885Sdumbbell	case CHIP_RV770:
379254885Sdumbbell	case CHIP_RV730:
380254885Sdumbbell	case CHIP_RV710:
381254885Sdumbbell	case CHIP_RV740:
382254885Sdumbbell		/* todo */
383254885Sdumbbell		break;
384254885Sdumbbell	case CHIP_CEDAR:
385254885Sdumbbell	case CHIP_REDWOOD:
386254885Sdumbbell	case CHIP_JUNIPER:
387254885Sdumbbell	case CHIP_CYPRESS:
388254885Sdumbbell	case CHIP_HEMLOCK:
389254885Sdumbbell		/* todo */
390254885Sdumbbell		break;
391254885Sdumbbell	default:
392254885Sdumbbell		DRM_ERROR("i2c: unhandled radeon chip\n");
393254885Sdumbbell		break;
394254885Sdumbbell	}
395254885Sdumbbell	return prescale;
396254885Sdumbbell}
397254885Sdumbbell
398254885Sdumbbell
399254885Sdumbbell/* hw i2c engine for r1xx-4xx hardware
400254885Sdumbbell * hw can buffer up to 15 bytes
401254885Sdumbbell */
402254885Sdumbbellstatic int r100_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
403254885Sdumbbell			    struct iic_msg *msgs, int num)
404254885Sdumbbell{
405254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
406254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
407254885Sdumbbell	struct iic_msg *p;
408254885Sdumbbell	int i, j, k, ret = 0;
409254885Sdumbbell	u32 prescale;
410254885Sdumbbell	u32 i2c_cntl_0, i2c_cntl_1, i2c_data;
411254885Sdumbbell	u32 tmp, reg;
412254885Sdumbbell
413254885Sdumbbell	sx_xlock(&rdev->dc_hw_i2c_mutex);
414254885Sdumbbell	/* take the pm lock since we need a constant sclk */
415254885Sdumbbell	sx_xlock(&rdev->pm.mutex);
416254885Sdumbbell
417254885Sdumbbell	prescale = radeon_get_i2c_prescale(rdev);
418254885Sdumbbell
419254885Sdumbbell	reg = ((prescale << RADEON_I2C_PRESCALE_SHIFT) |
420254885Sdumbbell	       RADEON_I2C_DRIVE_EN |
421254885Sdumbbell	       RADEON_I2C_START |
422254885Sdumbbell	       RADEON_I2C_STOP |
423254885Sdumbbell	       RADEON_I2C_GO);
424254885Sdumbbell
425254885Sdumbbell	if (rdev->is_atom_bios) {
426254885Sdumbbell		tmp = RREG32(RADEON_BIOS_6_SCRATCH);
427254885Sdumbbell		WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE);
428254885Sdumbbell	}
429254885Sdumbbell
430254885Sdumbbell	if (rec->mm_i2c) {
431254885Sdumbbell		i2c_cntl_0 = RADEON_I2C_CNTL_0;
432254885Sdumbbell		i2c_cntl_1 = RADEON_I2C_CNTL_1;
433254885Sdumbbell		i2c_data = RADEON_I2C_DATA;
434254885Sdumbbell	} else {
435254885Sdumbbell		i2c_cntl_0 = RADEON_DVI_I2C_CNTL_0;
436254885Sdumbbell		i2c_cntl_1 = RADEON_DVI_I2C_CNTL_1;
437254885Sdumbbell		i2c_data = RADEON_DVI_I2C_DATA;
438254885Sdumbbell
439254885Sdumbbell		switch (rdev->family) {
440254885Sdumbbell		case CHIP_R100:
441254885Sdumbbell		case CHIP_RV100:
442254885Sdumbbell		case CHIP_RS100:
443254885Sdumbbell		case CHIP_RV200:
444254885Sdumbbell		case CHIP_RS200:
445254885Sdumbbell		case CHIP_RS300:
446254885Sdumbbell			switch (rec->mask_clk_reg) {
447254885Sdumbbell			case RADEON_GPIO_DVI_DDC:
448254885Sdumbbell				/* no gpio select bit */
449254885Sdumbbell				break;
450254885Sdumbbell			default:
451254885Sdumbbell				DRM_ERROR("gpio not supported with hw i2c\n");
452282199Sdumbbell				ret = -EINVAL;
453254885Sdumbbell				goto done;
454254885Sdumbbell			}
455254885Sdumbbell			break;
456254885Sdumbbell		case CHIP_R200:
457254885Sdumbbell			/* only bit 4 on r200 */
458254885Sdumbbell			switch (rec->mask_clk_reg) {
459254885Sdumbbell			case RADEON_GPIO_DVI_DDC:
460254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
461254885Sdumbbell				break;
462254885Sdumbbell			case RADEON_GPIO_MONID:
463254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
464254885Sdumbbell				break;
465254885Sdumbbell			default:
466254885Sdumbbell				DRM_ERROR("gpio not supported with hw i2c\n");
467282199Sdumbbell				ret = -EINVAL;
468254885Sdumbbell				goto done;
469254885Sdumbbell			}
470254885Sdumbbell			break;
471254885Sdumbbell		case CHIP_RV250:
472254885Sdumbbell		case CHIP_RV280:
473254885Sdumbbell			/* bits 3 and 4 */
474254885Sdumbbell			switch (rec->mask_clk_reg) {
475254885Sdumbbell			case RADEON_GPIO_DVI_DDC:
476254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
477254885Sdumbbell				break;
478254885Sdumbbell			case RADEON_GPIO_VGA_DDC:
479254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2);
480254885Sdumbbell				break;
481254885Sdumbbell			case RADEON_GPIO_CRT2_DDC:
482254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
483254885Sdumbbell				break;
484254885Sdumbbell			default:
485254885Sdumbbell				DRM_ERROR("gpio not supported with hw i2c\n");
486282199Sdumbbell				ret = -EINVAL;
487254885Sdumbbell				goto done;
488254885Sdumbbell			}
489254885Sdumbbell			break;
490254885Sdumbbell		case CHIP_R300:
491254885Sdumbbell		case CHIP_R350:
492254885Sdumbbell			/* only bit 4 on r300/r350 */
493254885Sdumbbell			switch (rec->mask_clk_reg) {
494254885Sdumbbell			case RADEON_GPIO_VGA_DDC:
495254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
496254885Sdumbbell				break;
497254885Sdumbbell			case RADEON_GPIO_DVI_DDC:
498254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
499254885Sdumbbell				break;
500254885Sdumbbell			default:
501254885Sdumbbell				DRM_ERROR("gpio not supported with hw i2c\n");
502282199Sdumbbell				ret = -EINVAL;
503254885Sdumbbell				goto done;
504254885Sdumbbell			}
505254885Sdumbbell			break;
506254885Sdumbbell		case CHIP_RV350:
507254885Sdumbbell		case CHIP_RV380:
508254885Sdumbbell		case CHIP_R420:
509254885Sdumbbell		case CHIP_R423:
510254885Sdumbbell		case CHIP_RV410:
511254885Sdumbbell		case CHIP_RS400:
512254885Sdumbbell		case CHIP_RS480:
513254885Sdumbbell			/* bits 3 and 4 */
514254885Sdumbbell			switch (rec->mask_clk_reg) {
515254885Sdumbbell			case RADEON_GPIO_VGA_DDC:
516254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1);
517254885Sdumbbell				break;
518254885Sdumbbell			case RADEON_GPIO_DVI_DDC:
519254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC2);
520254885Sdumbbell				break;
521254885Sdumbbell			case RADEON_GPIO_MONID:
522254885Sdumbbell				reg |= R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3);
523254885Sdumbbell				break;
524254885Sdumbbell			default:
525254885Sdumbbell				DRM_ERROR("gpio not supported with hw i2c\n");
526282199Sdumbbell				ret = -EINVAL;
527254885Sdumbbell				goto done;
528254885Sdumbbell			}
529254885Sdumbbell			break;
530254885Sdumbbell		default:
531254885Sdumbbell			DRM_ERROR("unsupported asic\n");
532282199Sdumbbell			ret = -EINVAL;
533254885Sdumbbell			goto done;
534254885Sdumbbell			break;
535254885Sdumbbell		}
536254885Sdumbbell	}
537254885Sdumbbell
538254885Sdumbbell	/* check for bus probe */
539254885Sdumbbell	p = &msgs[0];
540254885Sdumbbell	if ((num == 1) && (p->len == 0)) {
541254885Sdumbbell		WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
542254885Sdumbbell				    RADEON_I2C_NACK |
543254885Sdumbbell				    RADEON_I2C_HALT |
544254885Sdumbbell				    RADEON_I2C_SOFT_RST));
545254885Sdumbbell		WREG32(i2c_data, (p->slave << 1) & 0xff);
546254885Sdumbbell		WREG32(i2c_data, 0);
547254885Sdumbbell		WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
548254885Sdumbbell				    (1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
549254885Sdumbbell				    RADEON_I2C_EN |
550254885Sdumbbell				    (48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
551254885Sdumbbell		WREG32(i2c_cntl_0, reg);
552254885Sdumbbell		for (k = 0; k < 32; k++) {
553282199Sdumbbell			udelay(10);
554254885Sdumbbell			tmp = RREG32(i2c_cntl_0);
555254885Sdumbbell			if (tmp & RADEON_I2C_GO)
556254885Sdumbbell				continue;
557254885Sdumbbell			tmp = RREG32(i2c_cntl_0);
558254885Sdumbbell			if (tmp & RADEON_I2C_DONE)
559254885Sdumbbell				break;
560254885Sdumbbell			else {
561254885Sdumbbell				DRM_DEBUG("i2c write error 0x%08x\n", tmp);
562254885Sdumbbell				WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
563282199Sdumbbell				ret = -EIO;
564254885Sdumbbell				goto done;
565254885Sdumbbell			}
566254885Sdumbbell		}
567254885Sdumbbell		goto done;
568254885Sdumbbell	}
569254885Sdumbbell
570254885Sdumbbell	for (i = 0; i < num; i++) {
571254885Sdumbbell		p = &msgs[i];
572254885Sdumbbell		for (j = 0; j < p->len; j++) {
573254885Sdumbbell			if (p->flags & IIC_M_RD) {
574254885Sdumbbell				WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
575254885Sdumbbell						    RADEON_I2C_NACK |
576254885Sdumbbell						    RADEON_I2C_HALT |
577254885Sdumbbell						    RADEON_I2C_SOFT_RST));
578254885Sdumbbell				WREG32(i2c_data, ((p->slave << 1) & 0xff) | 0x1);
579254885Sdumbbell				WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
580254885Sdumbbell						    (1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
581254885Sdumbbell						    RADEON_I2C_EN |
582254885Sdumbbell						    (48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
583254885Sdumbbell				WREG32(i2c_cntl_0, reg | RADEON_I2C_RECEIVE);
584254885Sdumbbell				for (k = 0; k < 32; k++) {
585282199Sdumbbell					udelay(10);
586254885Sdumbbell					tmp = RREG32(i2c_cntl_0);
587254885Sdumbbell					if (tmp & RADEON_I2C_GO)
588254885Sdumbbell						continue;
589254885Sdumbbell					tmp = RREG32(i2c_cntl_0);
590254885Sdumbbell					if (tmp & RADEON_I2C_DONE)
591254885Sdumbbell						break;
592254885Sdumbbell					else {
593254885Sdumbbell						DRM_DEBUG("i2c read error 0x%08x\n", tmp);
594254885Sdumbbell						WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
595282199Sdumbbell						ret = -EIO;
596254885Sdumbbell						goto done;
597254885Sdumbbell					}
598254885Sdumbbell				}
599254885Sdumbbell				p->buf[j] = RREG32(i2c_data) & 0xff;
600254885Sdumbbell			} else {
601254885Sdumbbell				WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
602254885Sdumbbell						    RADEON_I2C_NACK |
603254885Sdumbbell						    RADEON_I2C_HALT |
604254885Sdumbbell						    RADEON_I2C_SOFT_RST));
605254885Sdumbbell				WREG32(i2c_data, (p->slave << 1) & 0xff);
606254885Sdumbbell				WREG32(i2c_data, p->buf[j]);
607254885Sdumbbell				WREG32(i2c_cntl_1, ((1 << RADEON_I2C_DATA_COUNT_SHIFT) |
608254885Sdumbbell						    (1 << RADEON_I2C_ADDR_COUNT_SHIFT) |
609254885Sdumbbell						    RADEON_I2C_EN |
610254885Sdumbbell						    (48 << RADEON_I2C_TIME_LIMIT_SHIFT)));
611254885Sdumbbell				WREG32(i2c_cntl_0, reg);
612254885Sdumbbell				for (k = 0; k < 32; k++) {
613282199Sdumbbell					udelay(10);
614254885Sdumbbell					tmp = RREG32(i2c_cntl_0);
615254885Sdumbbell					if (tmp & RADEON_I2C_GO)
616254885Sdumbbell						continue;
617254885Sdumbbell					tmp = RREG32(i2c_cntl_0);
618254885Sdumbbell					if (tmp & RADEON_I2C_DONE)
619254885Sdumbbell						break;
620254885Sdumbbell					else {
621254885Sdumbbell						DRM_DEBUG("i2c write error 0x%08x\n", tmp);
622254885Sdumbbell						WREG32(i2c_cntl_0, tmp | RADEON_I2C_ABORT);
623282199Sdumbbell						ret = -EIO;
624254885Sdumbbell						goto done;
625254885Sdumbbell					}
626254885Sdumbbell				}
627254885Sdumbbell			}
628254885Sdumbbell		}
629254885Sdumbbell	}
630254885Sdumbbell
631254885Sdumbbelldone:
632254885Sdumbbell	WREG32(i2c_cntl_0, 0);
633254885Sdumbbell	WREG32(i2c_cntl_1, 0);
634254885Sdumbbell	WREG32(i2c_cntl_0, (RADEON_I2C_DONE |
635254885Sdumbbell			    RADEON_I2C_NACK |
636254885Sdumbbell			    RADEON_I2C_HALT |
637254885Sdumbbell			    RADEON_I2C_SOFT_RST));
638254885Sdumbbell
639254885Sdumbbell	if (rdev->is_atom_bios) {
640254885Sdumbbell		tmp = RREG32(RADEON_BIOS_6_SCRATCH);
641254885Sdumbbell		tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE;
642254885Sdumbbell		WREG32(RADEON_BIOS_6_SCRATCH, tmp);
643254885Sdumbbell	}
644254885Sdumbbell
645254885Sdumbbell	sx_xunlock(&rdev->pm.mutex);
646254885Sdumbbell	sx_xunlock(&rdev->dc_hw_i2c_mutex);
647254885Sdumbbell
648254885Sdumbbell	return ret;
649254885Sdumbbell}
650254885Sdumbbell
651254885Sdumbbell/* hw i2c engine for r5xx hardware
652254885Sdumbbell * hw can buffer up to 15 bytes
653254885Sdumbbell */
654254885Sdumbbellstatic int r500_hw_i2c_xfer(struct radeon_i2c_chan *i2c,
655254885Sdumbbell			    struct iic_msg *msgs, int num)
656254885Sdumbbell{
657254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
658254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
659254885Sdumbbell	struct iic_msg *p;
660254885Sdumbbell	int i, j, remaining, current_count, buffer_offset, ret = 0;
661254885Sdumbbell	u32 prescale;
662254885Sdumbbell	u32 tmp, reg;
663254885Sdumbbell	u32 saved1, saved2;
664254885Sdumbbell
665254885Sdumbbell	sx_xlock(&rdev->dc_hw_i2c_mutex);
666254885Sdumbbell	/* take the pm lock since we need a constant sclk */
667254885Sdumbbell	sx_xlock(&rdev->pm.mutex);
668254885Sdumbbell
669254885Sdumbbell	prescale = radeon_get_i2c_prescale(rdev);
670254885Sdumbbell
671254885Sdumbbell	/* clear gpio mask bits */
672254885Sdumbbell	tmp = RREG32(rec->mask_clk_reg);
673254885Sdumbbell	tmp &= ~rec->mask_clk_mask;
674254885Sdumbbell	WREG32(rec->mask_clk_reg, tmp);
675254885Sdumbbell	tmp = RREG32(rec->mask_clk_reg);
676254885Sdumbbell
677254885Sdumbbell	tmp = RREG32(rec->mask_data_reg);
678254885Sdumbbell	tmp &= ~rec->mask_data_mask;
679254885Sdumbbell	WREG32(rec->mask_data_reg, tmp);
680254885Sdumbbell	tmp = RREG32(rec->mask_data_reg);
681254885Sdumbbell
682254885Sdumbbell	/* clear pin values */
683254885Sdumbbell	tmp = RREG32(rec->a_clk_reg);
684254885Sdumbbell	tmp &= ~rec->a_clk_mask;
685254885Sdumbbell	WREG32(rec->a_clk_reg, tmp);
686254885Sdumbbell	tmp = RREG32(rec->a_clk_reg);
687254885Sdumbbell
688254885Sdumbbell	tmp = RREG32(rec->a_data_reg);
689254885Sdumbbell	tmp &= ~rec->a_data_mask;
690254885Sdumbbell	WREG32(rec->a_data_reg, tmp);
691254885Sdumbbell	tmp = RREG32(rec->a_data_reg);
692254885Sdumbbell
693254885Sdumbbell	/* set the pins to input */
694254885Sdumbbell	tmp = RREG32(rec->en_clk_reg);
695254885Sdumbbell	tmp &= ~rec->en_clk_mask;
696254885Sdumbbell	WREG32(rec->en_clk_reg, tmp);
697254885Sdumbbell	tmp = RREG32(rec->en_clk_reg);
698254885Sdumbbell
699254885Sdumbbell	tmp = RREG32(rec->en_data_reg);
700254885Sdumbbell	tmp &= ~rec->en_data_mask;
701254885Sdumbbell	WREG32(rec->en_data_reg, tmp);
702254885Sdumbbell	tmp = RREG32(rec->en_data_reg);
703254885Sdumbbell
704254885Sdumbbell	/* */
705254885Sdumbbell	tmp = RREG32(RADEON_BIOS_6_SCRATCH);
706254885Sdumbbell	WREG32(RADEON_BIOS_6_SCRATCH, tmp | ATOM_S6_HW_I2C_BUSY_STATE);
707254885Sdumbbell	saved1 = RREG32(AVIVO_DC_I2C_CONTROL1);
708254885Sdumbbell	saved2 = RREG32(0x494);
709254885Sdumbbell	WREG32(0x494, saved2 | 0x1);
710254885Sdumbbell
711254885Sdumbbell	WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_WANTS_TO_USE_I2C);
712254885Sdumbbell	for (i = 0; i < 50; i++) {
713282199Sdumbbell		udelay(1);
714254885Sdumbbell		if (RREG32(AVIVO_DC_I2C_ARBITRATION) & AVIVO_DC_I2C_SW_CAN_USE_I2C)
715254885Sdumbbell			break;
716254885Sdumbbell	}
717254885Sdumbbell	if (i == 50) {
718254885Sdumbbell		DRM_ERROR("failed to get i2c bus\n");
719282199Sdumbbell		ret = -EBUSY;
720254885Sdumbbell		goto done;
721254885Sdumbbell	}
722254885Sdumbbell
723254885Sdumbbell	reg = AVIVO_DC_I2C_START | AVIVO_DC_I2C_STOP | AVIVO_DC_I2C_EN;
724254885Sdumbbell	switch (rec->mask_clk_reg) {
725254885Sdumbbell	case AVIVO_DC_GPIO_DDC1_MASK:
726254885Sdumbbell		reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC1);
727254885Sdumbbell		break;
728254885Sdumbbell	case AVIVO_DC_GPIO_DDC2_MASK:
729254885Sdumbbell		reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC2);
730254885Sdumbbell		break;
731254885Sdumbbell	case AVIVO_DC_GPIO_DDC3_MASK:
732254885Sdumbbell		reg |= AVIVO_DC_I2C_PIN_SELECT(AVIVO_SEL_DDC3);
733254885Sdumbbell		break;
734254885Sdumbbell	default:
735254885Sdumbbell		DRM_ERROR("gpio not supported with hw i2c\n");
736282199Sdumbbell		ret = -EINVAL;
737254885Sdumbbell		goto done;
738254885Sdumbbell	}
739254885Sdumbbell
740254885Sdumbbell	/* check for bus probe */
741254885Sdumbbell	p = &msgs[0];
742254885Sdumbbell	if ((num == 1) && (p->len == 0)) {
743254885Sdumbbell		WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
744254885Sdumbbell					      AVIVO_DC_I2C_NACK |
745254885Sdumbbell					      AVIVO_DC_I2C_HALT));
746254885Sdumbbell		WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
747282199Sdumbbell		udelay(1);
748254885Sdumbbell		WREG32(AVIVO_DC_I2C_RESET, 0);
749254885Sdumbbell
750254885Sdumbbell		WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff);
751254885Sdumbbell		WREG32(AVIVO_DC_I2C_DATA, 0);
752254885Sdumbbell
753254885Sdumbbell		WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
754254885Sdumbbell		WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
755254885Sdumbbell					       AVIVO_DC_I2C_DATA_COUNT(1) |
756254885Sdumbbell					       (prescale << 16)));
757254885Sdumbbell		WREG32(AVIVO_DC_I2C_CONTROL1, reg);
758254885Sdumbbell		WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
759254885Sdumbbell		for (j = 0; j < 200; j++) {
760282199Sdumbbell			udelay(50);
761254885Sdumbbell			tmp = RREG32(AVIVO_DC_I2C_STATUS1);
762254885Sdumbbell			if (tmp & AVIVO_DC_I2C_GO)
763254885Sdumbbell				continue;
764254885Sdumbbell			tmp = RREG32(AVIVO_DC_I2C_STATUS1);
765254885Sdumbbell			if (tmp & AVIVO_DC_I2C_DONE)
766254885Sdumbbell				break;
767254885Sdumbbell			else {
768254885Sdumbbell				DRM_DEBUG("i2c write error 0x%08x\n", tmp);
769254885Sdumbbell				WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
770282199Sdumbbell				ret = -EIO;
771254885Sdumbbell				goto done;
772254885Sdumbbell			}
773254885Sdumbbell		}
774254885Sdumbbell		goto done;
775254885Sdumbbell	}
776254885Sdumbbell
777254885Sdumbbell	for (i = 0; i < num; i++) {
778254885Sdumbbell		p = &msgs[i];
779254885Sdumbbell		remaining = p->len;
780254885Sdumbbell		buffer_offset = 0;
781254885Sdumbbell		if (p->flags & IIC_M_RD) {
782254885Sdumbbell			while (remaining) {
783254885Sdumbbell				if (remaining > 15)
784254885Sdumbbell					current_count = 15;
785254885Sdumbbell				else
786254885Sdumbbell					current_count = remaining;
787254885Sdumbbell				WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
788254885Sdumbbell							      AVIVO_DC_I2C_NACK |
789254885Sdumbbell							      AVIVO_DC_I2C_HALT));
790254885Sdumbbell				WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
791282199Sdumbbell				udelay(1);
792254885Sdumbbell				WREG32(AVIVO_DC_I2C_RESET, 0);
793254885Sdumbbell
794254885Sdumbbell				WREG32(AVIVO_DC_I2C_DATA, ((p->slave << 1) & 0xff) | 0x1);
795254885Sdumbbell				WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
796254885Sdumbbell				WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
797254885Sdumbbell							       AVIVO_DC_I2C_DATA_COUNT(current_count) |
798254885Sdumbbell							       (prescale << 16)));
799254885Sdumbbell				WREG32(AVIVO_DC_I2C_CONTROL1, reg | AVIVO_DC_I2C_RECEIVE);
800254885Sdumbbell				WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
801254885Sdumbbell				for (j = 0; j < 200; j++) {
802282199Sdumbbell					udelay(50);
803254885Sdumbbell					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
804254885Sdumbbell					if (tmp & AVIVO_DC_I2C_GO)
805254885Sdumbbell						continue;
806254885Sdumbbell					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
807254885Sdumbbell					if (tmp & AVIVO_DC_I2C_DONE)
808254885Sdumbbell						break;
809254885Sdumbbell					else {
810254885Sdumbbell						DRM_DEBUG("i2c read error 0x%08x\n", tmp);
811254885Sdumbbell						WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
812282199Sdumbbell						ret = -EIO;
813254885Sdumbbell						goto done;
814254885Sdumbbell					}
815254885Sdumbbell				}
816254885Sdumbbell				for (j = 0; j < current_count; j++)
817254885Sdumbbell					p->buf[buffer_offset + j] = RREG32(AVIVO_DC_I2C_DATA) & 0xff;
818254885Sdumbbell				remaining -= current_count;
819254885Sdumbbell				buffer_offset += current_count;
820254885Sdumbbell			}
821254885Sdumbbell		} else {
822254885Sdumbbell			while (remaining) {
823254885Sdumbbell				if (remaining > 15)
824254885Sdumbbell					current_count = 15;
825254885Sdumbbell				else
826254885Sdumbbell					current_count = remaining;
827254885Sdumbbell				WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
828254885Sdumbbell							      AVIVO_DC_I2C_NACK |
829254885Sdumbbell							      AVIVO_DC_I2C_HALT));
830254885Sdumbbell				WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
831282199Sdumbbell				udelay(1);
832254885Sdumbbell				WREG32(AVIVO_DC_I2C_RESET, 0);
833254885Sdumbbell
834254885Sdumbbell				WREG32(AVIVO_DC_I2C_DATA, (p->slave << 1) & 0xff);
835254885Sdumbbell				for (j = 0; j < current_count; j++)
836254885Sdumbbell					WREG32(AVIVO_DC_I2C_DATA, p->buf[buffer_offset + j]);
837254885Sdumbbell
838254885Sdumbbell				WREG32(AVIVO_DC_I2C_CONTROL3, AVIVO_DC_I2C_TIME_LIMIT(48));
839254885Sdumbbell				WREG32(AVIVO_DC_I2C_CONTROL2, (AVIVO_DC_I2C_ADDR_COUNT(1) |
840254885Sdumbbell							       AVIVO_DC_I2C_DATA_COUNT(current_count) |
841254885Sdumbbell							       (prescale << 16)));
842254885Sdumbbell				WREG32(AVIVO_DC_I2C_CONTROL1, reg);
843254885Sdumbbell				WREG32(AVIVO_DC_I2C_STATUS1, AVIVO_DC_I2C_GO);
844254885Sdumbbell				for (j = 0; j < 200; j++) {
845282199Sdumbbell					udelay(50);
846254885Sdumbbell					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
847254885Sdumbbell					if (tmp & AVIVO_DC_I2C_GO)
848254885Sdumbbell						continue;
849254885Sdumbbell					tmp = RREG32(AVIVO_DC_I2C_STATUS1);
850254885Sdumbbell					if (tmp & AVIVO_DC_I2C_DONE)
851254885Sdumbbell						break;
852254885Sdumbbell					else {
853254885Sdumbbell						DRM_DEBUG("i2c write error 0x%08x\n", tmp);
854254885Sdumbbell						WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_ABORT);
855282199Sdumbbell						ret = -EIO;
856254885Sdumbbell						goto done;
857254885Sdumbbell					}
858254885Sdumbbell				}
859254885Sdumbbell				remaining -= current_count;
860254885Sdumbbell				buffer_offset += current_count;
861254885Sdumbbell			}
862254885Sdumbbell		}
863254885Sdumbbell	}
864254885Sdumbbell
865254885Sdumbbelldone:
866254885Sdumbbell	WREG32(AVIVO_DC_I2C_STATUS1, (AVIVO_DC_I2C_DONE |
867254885Sdumbbell				      AVIVO_DC_I2C_NACK |
868254885Sdumbbell				      AVIVO_DC_I2C_HALT));
869254885Sdumbbell	WREG32(AVIVO_DC_I2C_RESET, AVIVO_DC_I2C_SOFT_RESET);
870282199Sdumbbell	udelay(1);
871254885Sdumbbell	WREG32(AVIVO_DC_I2C_RESET, 0);
872254885Sdumbbell
873254885Sdumbbell	WREG32(AVIVO_DC_I2C_ARBITRATION, AVIVO_DC_I2C_SW_DONE_USING_I2C);
874254885Sdumbbell	WREG32(AVIVO_DC_I2C_CONTROL1, saved1);
875254885Sdumbbell	WREG32(0x494, saved2);
876254885Sdumbbell	tmp = RREG32(RADEON_BIOS_6_SCRATCH);
877254885Sdumbbell	tmp &= ~ATOM_S6_HW_I2C_BUSY_STATE;
878254885Sdumbbell	WREG32(RADEON_BIOS_6_SCRATCH, tmp);
879254885Sdumbbell
880254885Sdumbbell	sx_xunlock(&rdev->pm.mutex);
881254885Sdumbbell	sx_xunlock(&rdev->dc_hw_i2c_mutex);
882254885Sdumbbell
883254885Sdumbbell	return ret;
884254885Sdumbbell}
885254885Sdumbbell
886254885Sdumbbellstatic int radeon_hw_i2c_xfer(device_t dev,
887254885Sdumbbell			      struct iic_msg *msgs, uint32_t num)
888254885Sdumbbell{
889254885Sdumbbell	struct radeon_i2c_chan *i2c = device_get_softc(dev);
890254885Sdumbbell	struct radeon_device *rdev = i2c->dev->dev_private;
891254885Sdumbbell	struct radeon_i2c_bus_rec *rec = &i2c->rec;
892254885Sdumbbell	int ret = 0;
893254885Sdumbbell
894254885Sdumbbell	switch (rdev->family) {
895254885Sdumbbell	case CHIP_R100:
896254885Sdumbbell	case CHIP_RV100:
897254885Sdumbbell	case CHIP_RS100:
898254885Sdumbbell	case CHIP_RV200:
899254885Sdumbbell	case CHIP_RS200:
900254885Sdumbbell	case CHIP_R200:
901254885Sdumbbell	case CHIP_RV250:
902254885Sdumbbell	case CHIP_RS300:
903254885Sdumbbell	case CHIP_RV280:
904254885Sdumbbell	case CHIP_R300:
905254885Sdumbbell	case CHIP_R350:
906254885Sdumbbell	case CHIP_RV350:
907254885Sdumbbell	case CHIP_RV380:
908254885Sdumbbell	case CHIP_R420:
909254885Sdumbbell	case CHIP_R423:
910254885Sdumbbell	case CHIP_RV410:
911254885Sdumbbell	case CHIP_RS400:
912254885Sdumbbell	case CHIP_RS480:
913254885Sdumbbell		ret = r100_hw_i2c_xfer(i2c, msgs, num);
914254885Sdumbbell		break;
915254885Sdumbbell	case CHIP_RS600:
916254885Sdumbbell	case CHIP_RS690:
917254885Sdumbbell	case CHIP_RS740:
918254885Sdumbbell		/* XXX fill in hw i2c implementation */
919254885Sdumbbell		break;
920254885Sdumbbell	case CHIP_RV515:
921254885Sdumbbell	case CHIP_R520:
922254885Sdumbbell	case CHIP_RV530:
923254885Sdumbbell	case CHIP_RV560:
924254885Sdumbbell	case CHIP_RV570:
925254885Sdumbbell	case CHIP_R580:
926254885Sdumbbell		if (rec->mm_i2c)
927254885Sdumbbell			ret = r100_hw_i2c_xfer(i2c, msgs, num);
928254885Sdumbbell		else
929254885Sdumbbell			ret = r500_hw_i2c_xfer(i2c, msgs, num);
930254885Sdumbbell		break;
931254885Sdumbbell	case CHIP_R600:
932254885Sdumbbell	case CHIP_RV610:
933254885Sdumbbell	case CHIP_RV630:
934254885Sdumbbell	case CHIP_RV670:
935254885Sdumbbell		/* XXX fill in hw i2c implementation */
936254885Sdumbbell		break;
937254885Sdumbbell	case CHIP_RV620:
938254885Sdumbbell	case CHIP_RV635:
939254885Sdumbbell	case CHIP_RS780:
940254885Sdumbbell	case CHIP_RS880:
941254885Sdumbbell	case CHIP_RV770:
942254885Sdumbbell	case CHIP_RV730:
943254885Sdumbbell	case CHIP_RV710:
944254885Sdumbbell	case CHIP_RV740:
945254885Sdumbbell		/* XXX fill in hw i2c implementation */
946254885Sdumbbell		break;
947254885Sdumbbell	case CHIP_CEDAR:
948254885Sdumbbell	case CHIP_REDWOOD:
949254885Sdumbbell	case CHIP_JUNIPER:
950254885Sdumbbell	case CHIP_CYPRESS:
951254885Sdumbbell	case CHIP_HEMLOCK:
952254885Sdumbbell		/* XXX fill in hw i2c implementation */
953254885Sdumbbell		break;
954254885Sdumbbell	default:
955254885Sdumbbell		DRM_ERROR("i2c: unhandled radeon chip\n");
956282199Sdumbbell		ret = -EIO;
957254885Sdumbbell		break;
958254885Sdumbbell	}
959254885Sdumbbell
960282199Sdumbbell	return -ret;
961254885Sdumbbell}
962254885Sdumbbell
963254885Sdumbbellstatic int
964254885Sdumbbellradeon_hw_i2c_probe(device_t dev)
965254885Sdumbbell{
966254885Sdumbbell
967254885Sdumbbell	return (BUS_PROBE_SPECIFIC);
968254885Sdumbbell}
969254885Sdumbbell
970254885Sdumbbellstatic int
971254885Sdumbbellradeon_hw_i2c_attach(device_t dev)
972254885Sdumbbell{
973254885Sdumbbell	struct radeon_i2c_chan *i2c;
974254885Sdumbbell	device_t iic_dev;
975254885Sdumbbell
976254885Sdumbbell	i2c = device_get_softc(dev);
977254885Sdumbbell	device_set_desc(dev, i2c->name);
978254885Sdumbbell
979254885Sdumbbell	/* add generic bit-banging code */
980254885Sdumbbell	iic_dev = device_add_child(dev, "iicbus", -1);
981254885Sdumbbell	if (iic_dev == NULL)
982254885Sdumbbell		return (ENXIO);
983254885Sdumbbell	device_quiet(iic_dev);
984254885Sdumbbell
985254885Sdumbbell	/* attach and probe added child */
986254885Sdumbbell	bus_generic_attach(dev);
987254885Sdumbbell
988254885Sdumbbell	return (0);
989254885Sdumbbell}
990254885Sdumbbell
991254885Sdumbbellstatic int
992254885Sdumbbellradeon_hw_i2c_detach(device_t dev)
993254885Sdumbbell{
994254885Sdumbbell
995254885Sdumbbell	/* detach bit-banding code. */
996254885Sdumbbell	bus_generic_detach(dev);
997254885Sdumbbell
998254885Sdumbbell	/* delete bit-banding code. */
999254885Sdumbbell	device_delete_children(dev);
1000254885Sdumbbell	return (0);
1001254885Sdumbbell}
1002254885Sdumbbell
1003254885Sdumbbellstatic int
1004254885Sdumbbellradeon_hw_i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
1005254885Sdumbbell{
1006254885Sdumbbell
1007254885Sdumbbell	/* Not sure what to do here. */
1008254885Sdumbbell	return 0;
1009254885Sdumbbell}
1010254885Sdumbbell
1011254885Sdumbbell
1012254885Sdumbbellstatic device_method_t radeon_hw_i2c_methods[] = {
1013254885Sdumbbell	DEVMETHOD(device_probe,		radeon_hw_i2c_probe),
1014254885Sdumbbell	DEVMETHOD(device_attach,	radeon_hw_i2c_attach),
1015254885Sdumbbell	DEVMETHOD(device_detach,	radeon_hw_i2c_detach),
1016254885Sdumbbell	DEVMETHOD(iicbus_reset,		radeon_hw_i2c_reset),
1017254885Sdumbbell	DEVMETHOD(iicbus_transfer,	radeon_hw_i2c_xfer),
1018254885Sdumbbell	DEVMETHOD_END
1019254885Sdumbbell};
1020254885Sdumbbell
1021254885Sdumbbellstatic driver_t radeon_hw_i2c_driver = {
1022254885Sdumbbell	"radeon_hw_i2c",
1023254885Sdumbbell	radeon_hw_i2c_methods,
1024254885Sdumbbell	0 /* softc will be allocated by parent */
1025254885Sdumbbell};
1026254885Sdumbbell
1027254885Sdumbbellstatic devclass_t radeon_hw_i2c_devclass;
1028254885SdumbbellDRIVER_MODULE_ORDERED(radeon_hw_i2c, drm, radeon_hw_i2c_driver,
1029254885Sdumbbell    radeon_hw_i2c_devclass, 0, 0, SI_ORDER_FIRST);
1030254885SdumbbellDRIVER_MODULE(iicbus, radeon_hw_i2c, iicbus_driver, iicbus_devclass, 0, 0);
1031254885Sdumbbell
1032254885Sdumbbellstruct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
1033254885Sdumbbell					  struct radeon_i2c_bus_rec *rec,
1034254885Sdumbbell					  const char *name)
1035254885Sdumbbell{
1036254885Sdumbbell	struct radeon_device *rdev = dev->dev_private;
1037254885Sdumbbell	struct radeon_i2c_chan *i2c;
1038254885Sdumbbell	device_t iicbus_dev;
1039254885Sdumbbell	int ret;
1040254885Sdumbbell
1041254885Sdumbbell	/* don't add the mm_i2c bus unless hw_i2c is enabled */
1042254885Sdumbbell	if (rec->mm_i2c && (radeon_hw_i2c == 0))
1043254885Sdumbbell		return NULL;
1044254885Sdumbbell
1045254885Sdumbbell	i2c = malloc(sizeof(struct radeon_i2c_chan),
1046282199Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1047254885Sdumbbell	if (i2c == NULL)
1048254885Sdumbbell		return NULL;
1049254885Sdumbbell
1050254885Sdumbbell	/*
1051254885Sdumbbell	 * Grab Giant before messing with newbus devices, just in case
1052254885Sdumbbell	 * we do not hold it already.
1053254885Sdumbbell	 */
1054254885Sdumbbell	mtx_lock(&Giant);
1055254885Sdumbbell
1056254885Sdumbbell	i2c->rec = *rec;
1057254885Sdumbbell	i2c->dev = dev;
1058254885Sdumbbell	if (rec->mm_i2c ||
1059254885Sdumbbell	    (rec->hw_capable &&
1060254885Sdumbbell	     radeon_hw_i2c &&
1061254885Sdumbbell	     ((rdev->family <= CHIP_RS480) ||
1062254885Sdumbbell	      ((rdev->family >= CHIP_RV515) && (rdev->family <= CHIP_R580))))) {
1063254885Sdumbbell		/* set the radeon hw i2c adapter */
1064254885Sdumbbell		snprintf(i2c->name, sizeof(i2c->name),
1065254885Sdumbbell			 "Radeon i2c hw bus %s", name);
1066282199Sdumbbell		iicbus_dev = device_add_child(dev->dev, "radeon_hw_i2c", -1);
1067254885Sdumbbell		if (iicbus_dev == NULL) {
1068254885Sdumbbell			DRM_ERROR("Failed to create bridge for hw i2c %s\n",
1069254885Sdumbbell			    name);
1070254885Sdumbbell			goto out_free;
1071254885Sdumbbell		}
1072254885Sdumbbell		device_quiet(iicbus_dev);
1073254885Sdumbbell		device_set_softc(iicbus_dev, i2c);
1074254885Sdumbbell
1075254885Sdumbbell		ret = device_probe_and_attach(iicbus_dev);
1076254885Sdumbbell		if (ret != 0) {
1077254885Sdumbbell			DRM_ERROR("Attach failed for bridge for hw i2c %s\n",
1078254885Sdumbbell			    name);
1079282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1080254885Sdumbbell			goto out_free;
1081254885Sdumbbell		}
1082254885Sdumbbell
1083254885Sdumbbell		i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1);
1084254885Sdumbbell		if (i2c->adapter == NULL) {
1085254885Sdumbbell			DRM_ERROR("hw i2c bridge doesn't have iicbus child\n");
1086282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1087254885Sdumbbell			goto out_free;
1088254885Sdumbbell		}
1089254885Sdumbbell	} else if (rec->hw_capable &&
1090254885Sdumbbell		   radeon_hw_i2c &&
1091254885Sdumbbell		   ASIC_IS_DCE3(rdev)) {
1092254885Sdumbbell		/* hw i2c using atom */
1093254885Sdumbbell		snprintf(i2c->name, sizeof(i2c->name),
1094254885Sdumbbell			 "Radeon i2c hw bus %s", name);
1095282199Sdumbbell		iicbus_dev = device_add_child(dev->dev, "radeon_atom_hw_i2c", -1);
1096254885Sdumbbell		if (iicbus_dev == NULL) {
1097254885Sdumbbell			DRM_ERROR("Failed to create bridge for hw i2c %s\n",
1098254885Sdumbbell			    name);
1099254885Sdumbbell			goto out_free;
1100254885Sdumbbell		}
1101254885Sdumbbell		device_quiet(iicbus_dev);
1102254885Sdumbbell		device_set_softc(iicbus_dev, i2c);
1103254885Sdumbbell
1104254885Sdumbbell		ret = device_probe_and_attach(iicbus_dev);
1105254885Sdumbbell		if (ret != 0) {
1106254885Sdumbbell			DRM_ERROR("Attach failed for bridge for hw i2c %s\n",
1107254885Sdumbbell			    name);
1108282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1109254885Sdumbbell			goto out_free;
1110254885Sdumbbell		}
1111254885Sdumbbell
1112254885Sdumbbell		i2c->adapter = device_find_child(iicbus_dev, "iicbus", -1);
1113254885Sdumbbell		if (i2c->adapter == NULL) {
1114254885Sdumbbell			DRM_ERROR("hw i2c bridge doesn't have iicbus child\n");
1115282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1116254885Sdumbbell			goto out_free;
1117254885Sdumbbell		}
1118254885Sdumbbell	} else {
1119254885Sdumbbell		device_t iicbb_dev;
1120254885Sdumbbell
1121254885Sdumbbell		/* set the radeon bit adapter */
1122254885Sdumbbell		snprintf(i2c->name, sizeof(i2c->name),
1123254885Sdumbbell			 "Radeon i2c bit bus %s", name);
1124282199Sdumbbell		iicbus_dev = device_add_child(dev->dev, "radeon_iicbb", -1);
1125254885Sdumbbell		if (iicbus_dev == NULL) {
1126254885Sdumbbell			DRM_ERROR("Failed to create bridge for bb i2c %s\n",
1127254885Sdumbbell			    name);
1128254885Sdumbbell			goto out_free;
1129254885Sdumbbell		}
1130254885Sdumbbell		device_quiet(iicbus_dev);
1131254885Sdumbbell		device_set_softc(iicbus_dev, i2c);
1132254885Sdumbbell
1133254885Sdumbbell		ret = device_probe_and_attach(iicbus_dev);
1134254885Sdumbbell		if (ret != 0) {
1135254885Sdumbbell			DRM_ERROR("Attach failed for bridge for bb i2c %s\n",
1136254885Sdumbbell			    name);
1137282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1138254885Sdumbbell			goto out_free;
1139254885Sdumbbell		}
1140254885Sdumbbell
1141254885Sdumbbell		iicbb_dev = device_find_child(iicbus_dev, "iicbb", -1);
1142254885Sdumbbell		if (iicbb_dev == NULL) {
1143254885Sdumbbell			DRM_ERROR("bb i2c bridge doesn't have iicbb child\n");
1144282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1145254885Sdumbbell			goto out_free;
1146254885Sdumbbell		}
1147254885Sdumbbell
1148254885Sdumbbell		i2c->adapter = device_find_child(iicbb_dev, "iicbus", -1);
1149254885Sdumbbell		if (i2c->adapter == NULL) {
1150254885Sdumbbell			DRM_ERROR(
1151254885Sdumbbell			    "bbbus bridge doesn't have iicbus grandchild\n");
1152282199Sdumbbell			device_delete_child(dev->dev, iicbus_dev);
1153254885Sdumbbell			goto out_free;
1154254885Sdumbbell		}
1155254885Sdumbbell	}
1156254885Sdumbbell
1157254885Sdumbbell	i2c->iic_bus = iicbus_dev;
1158254885Sdumbbell
1159254885Sdumbbell	mtx_unlock(&Giant);
1160254885Sdumbbell
1161254885Sdumbbell	return i2c;
1162254885Sdumbbellout_free:
1163254885Sdumbbell	mtx_unlock(&Giant);
1164254885Sdumbbell	free(i2c, DRM_MEM_DRIVER);
1165254885Sdumbbell	return NULL;
1166254885Sdumbbell
1167254885Sdumbbell}
1168254885Sdumbbell
1169254885Sdumbbellstruct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev,
1170254885Sdumbbell					     struct radeon_i2c_bus_rec *rec,
1171254885Sdumbbell					     const char *name)
1172254885Sdumbbell{
1173254885Sdumbbell	struct radeon_i2c_chan *i2c;
1174254885Sdumbbell	int ret;
1175254885Sdumbbell
1176254885Sdumbbell	i2c = malloc(sizeof(struct radeon_i2c_chan),
1177282199Sdumbbell	    DRM_MEM_DRIVER, M_NOWAIT | M_ZERO);
1178254885Sdumbbell	if (i2c == NULL)
1179254885Sdumbbell		return NULL;
1180254885Sdumbbell
1181254885Sdumbbell	i2c->rec = *rec;
1182254885Sdumbbell	i2c->dev = dev;
1183254885Sdumbbell	snprintf(i2c->name, sizeof(i2c->name),
1184254885Sdumbbell		 "Radeon aux bus %s", name);
1185282199Sdumbbell	ret = iic_dp_aux_add_bus(dev->dev, i2c->name,
1186254885Sdumbbell	    radeon_dp_i2c_aux_ch, i2c, &i2c->iic_bus,
1187254885Sdumbbell	    &i2c->adapter);
1188254885Sdumbbell	if (ret) {
1189254885Sdumbbell		DRM_INFO("Failed to register i2c %s\n", name);
1190254885Sdumbbell		goto out_free;
1191254885Sdumbbell	}
1192254885Sdumbbell
1193254885Sdumbbell	return i2c;
1194254885Sdumbbellout_free:
1195254885Sdumbbell	free(i2c, DRM_MEM_DRIVER);
1196254885Sdumbbell	return NULL;
1197254885Sdumbbell
1198254885Sdumbbell}
1199254885Sdumbbell
1200254885Sdumbbellvoid radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
1201254885Sdumbbell{
1202254885Sdumbbell	if (!i2c)
1203254885Sdumbbell		return;
1204254885Sdumbbell	if (i2c->iic_bus != NULL) {
1205254885Sdumbbell		int ret;
1206254885Sdumbbell
1207254885Sdumbbell		mtx_lock(&Giant);
1208282199Sdumbbell		ret = device_delete_child(i2c->dev->dev, i2c->iic_bus);
1209254885Sdumbbell		mtx_unlock(&Giant);
1210254885Sdumbbell		KASSERT(ret == 0, ("unable to detach iic bus %s: %d",
1211254885Sdumbbell		    i2c->name, ret));
1212254885Sdumbbell	}
1213254885Sdumbbell	free(i2c, DRM_MEM_DRIVER);
1214254885Sdumbbell}
1215254885Sdumbbell
1216254885Sdumbbell/* Add the default buses */
1217254885Sdumbbellvoid radeon_i2c_init(struct radeon_device *rdev)
1218254885Sdumbbell{
1219254885Sdumbbell	if (rdev->is_atom_bios)
1220254885Sdumbbell		radeon_atombios_i2c_init(rdev);
1221254885Sdumbbell	else
1222254885Sdumbbell		radeon_combios_i2c_init(rdev);
1223254885Sdumbbell}
1224254885Sdumbbell
1225254885Sdumbbell/* remove all the buses */
1226254885Sdumbbellvoid radeon_i2c_fini(struct radeon_device *rdev)
1227254885Sdumbbell{
1228254885Sdumbbell	int i;
1229254885Sdumbbell
1230254885Sdumbbell	for (i = 0; i < RADEON_MAX_I2C_BUS; i++) {
1231254885Sdumbbell		if (rdev->i2c_bus[i]) {
1232254885Sdumbbell			radeon_i2c_destroy(rdev->i2c_bus[i]);
1233254885Sdumbbell			rdev->i2c_bus[i] = NULL;
1234254885Sdumbbell		}
1235254885Sdumbbell	}
1236254885Sdumbbell}
1237254885Sdumbbell
1238254885Sdumbbell/* Add additional buses */
1239254885Sdumbbellvoid radeon_i2c_add(struct radeon_device *rdev,
1240254885Sdumbbell		    struct radeon_i2c_bus_rec *rec,
1241254885Sdumbbell		    const char *name)
1242254885Sdumbbell{
1243254885Sdumbbell	struct drm_device *dev = rdev->ddev;
1244254885Sdumbbell	int i;
1245254885Sdumbbell
1246254885Sdumbbell	for (i = 0; i < RADEON_MAX_I2C_BUS; i++) {
1247254885Sdumbbell		if (!rdev->i2c_bus[i]) {
1248254885Sdumbbell			rdev->i2c_bus[i] = radeon_i2c_create(dev, rec, name);
1249254885Sdumbbell			return;
1250254885Sdumbbell		}
1251254885Sdumbbell	}
1252254885Sdumbbell}
1253254885Sdumbbell
1254254885Sdumbbell/* looks up bus based on id */
1255254885Sdumbbellstruct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev,
1256254885Sdumbbell					  struct radeon_i2c_bus_rec *i2c_bus)
1257254885Sdumbbell{
1258254885Sdumbbell	int i;
1259254885Sdumbbell
1260254885Sdumbbell	for (i = 0; i < RADEON_MAX_I2C_BUS; i++) {
1261254885Sdumbbell		if (rdev->i2c_bus[i] &&
1262254885Sdumbbell		    (rdev->i2c_bus[i]->rec.i2c_id == i2c_bus->i2c_id)) {
1263254885Sdumbbell			return rdev->i2c_bus[i];
1264254885Sdumbbell		}
1265254885Sdumbbell	}
1266254885Sdumbbell	return NULL;
1267254885Sdumbbell}
1268254885Sdumbbell
1269254885Sdumbbellstruct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
1270254885Sdumbbell{
1271254885Sdumbbell	return NULL;
1272254885Sdumbbell}
1273254885Sdumbbell
1274254885Sdumbbellvoid radeon_i2c_get_byte(struct radeon_i2c_chan *i2c_bus,
1275254885Sdumbbell			 u8 slave_addr,
1276254885Sdumbbell			 u8 addr,
1277254885Sdumbbell			 u8 *val)
1278254885Sdumbbell{
1279254885Sdumbbell	u8 out_buf[2];
1280254885Sdumbbell	u8 in_buf[2];
1281254885Sdumbbell	struct iic_msg msgs[] = {
1282254885Sdumbbell		{
1283254885Sdumbbell			.slave = slave_addr << 1,
1284254885Sdumbbell			.flags = 0,
1285254885Sdumbbell			.len = 1,
1286254885Sdumbbell			.buf = out_buf,
1287254885Sdumbbell		},
1288254885Sdumbbell		{
1289254885Sdumbbell			.slave = slave_addr << 1,
1290254885Sdumbbell			.flags = IIC_M_RD,
1291254885Sdumbbell			.len = 1,
1292254885Sdumbbell			.buf = in_buf,
1293254885Sdumbbell		}
1294254885Sdumbbell	};
1295254885Sdumbbell
1296254885Sdumbbell	out_buf[0] = addr;
1297254885Sdumbbell	out_buf[1] = 0;
1298254885Sdumbbell
1299254885Sdumbbell	if (iicbus_transfer(i2c_bus->adapter, msgs, 2) == 0) {
1300254885Sdumbbell		*val = in_buf[0];
1301254885Sdumbbell		DRM_DEBUG("val = 0x%02x\n", *val);
1302254885Sdumbbell	} else {
1303254885Sdumbbell		DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n",
1304254885Sdumbbell			  addr, *val);
1305254885Sdumbbell	}
1306254885Sdumbbell}
1307254885Sdumbbell
1308254885Sdumbbellvoid radeon_i2c_put_byte(struct radeon_i2c_chan *i2c_bus,
1309254885Sdumbbell			 u8 slave_addr,
1310254885Sdumbbell			 u8 addr,
1311254885Sdumbbell			 u8 val)
1312254885Sdumbbell{
1313254885Sdumbbell	uint8_t out_buf[2];
1314254885Sdumbbell	struct iic_msg msg = {
1315254885Sdumbbell		.slave = slave_addr << 1,
1316254885Sdumbbell		.flags = 0,
1317254885Sdumbbell		.len = 2,
1318254885Sdumbbell		.buf = out_buf,
1319254885Sdumbbell	};
1320254885Sdumbbell
1321254885Sdumbbell	out_buf[0] = addr;
1322254885Sdumbbell	out_buf[1] = val;
1323254885Sdumbbell
1324254885Sdumbbell	if (iicbus_transfer(i2c_bus->adapter, &msg, 1) != 0)
1325254885Sdumbbell		DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n",
1326254885Sdumbbell			  addr, val);
1327254885Sdumbbell}
1328254885Sdumbbell
1329254885Sdumbbell/* ddc router switching */
1330254885Sdumbbellvoid radeon_router_select_ddc_port(struct radeon_connector *radeon_connector)
1331254885Sdumbbell{
1332254885Sdumbbell	u8 val;
1333254885Sdumbbell
1334254885Sdumbbell	if (!radeon_connector->router.ddc_valid)
1335254885Sdumbbell		return;
1336254885Sdumbbell
1337254885Sdumbbell	if (!radeon_connector->router_bus)
1338254885Sdumbbell		return;
1339254885Sdumbbell
1340254885Sdumbbell	radeon_i2c_get_byte(radeon_connector->router_bus,
1341254885Sdumbbell			    radeon_connector->router.i2c_addr,
1342254885Sdumbbell			    0x3, &val);
1343254885Sdumbbell	val &= ~radeon_connector->router.ddc_mux_control_pin;
1344254885Sdumbbell	radeon_i2c_put_byte(radeon_connector->router_bus,
1345254885Sdumbbell			    radeon_connector->router.i2c_addr,
1346254885Sdumbbell			    0x3, val);
1347254885Sdumbbell	radeon_i2c_get_byte(radeon_connector->router_bus,
1348254885Sdumbbell			    radeon_connector->router.i2c_addr,
1349254885Sdumbbell			    0x1, &val);
1350254885Sdumbbell	val &= ~radeon_connector->router.ddc_mux_control_pin;
1351254885Sdumbbell	val |= radeon_connector->router.ddc_mux_state;
1352254885Sdumbbell	radeon_i2c_put_byte(radeon_connector->router_bus,
1353254885Sdumbbell			    radeon_connector->router.i2c_addr,
1354254885Sdumbbell			    0x1, val);
1355254885Sdumbbell}
1356254885Sdumbbell
1357254885Sdumbbell/* clock/data router switching */
1358254885Sdumbbellvoid radeon_router_select_cd_port(struct radeon_connector *radeon_connector)
1359254885Sdumbbell{
1360254885Sdumbbell	u8 val;
1361254885Sdumbbell
1362254885Sdumbbell	if (!radeon_connector->router.cd_valid)
1363254885Sdumbbell		return;
1364254885Sdumbbell
1365254885Sdumbbell	if (!radeon_connector->router_bus)
1366254885Sdumbbell		return;
1367254885Sdumbbell
1368254885Sdumbbell	radeon_i2c_get_byte(radeon_connector->router_bus,
1369254885Sdumbbell			    radeon_connector->router.i2c_addr,
1370254885Sdumbbell			    0x3, &val);
1371254885Sdumbbell	val &= ~radeon_connector->router.cd_mux_control_pin;
1372254885Sdumbbell	radeon_i2c_put_byte(radeon_connector->router_bus,
1373254885Sdumbbell			    radeon_connector->router.i2c_addr,
1374254885Sdumbbell			    0x3, val);
1375254885Sdumbbell	radeon_i2c_get_byte(radeon_connector->router_bus,
1376254885Sdumbbell			    radeon_connector->router.i2c_addr,
1377254885Sdumbbell			    0x1, &val);
1378254885Sdumbbell	val &= ~radeon_connector->router.cd_mux_control_pin;
1379254885Sdumbbell	val |= radeon_connector->router.cd_mux_state;
1380254885Sdumbbell	radeon_i2c_put_byte(radeon_connector->router_bus,
1381254885Sdumbbell			    radeon_connector->router.i2c_addr,
1382254885Sdumbbell			    0x1, val);
1383254885Sdumbbell}
1384254885Sdumbbell
1385