2 * Copyright © 2009 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/delay.h>
26 #include <linux/slab.h>
27 #include <linux/init.h>
28 #include <linux/errno.h>
29 #include <linux/sched.h>
30 #include <linux/i2c.h>
34 /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
36 #define MODE_I2C_START 1
37 #define MODE_I2C_WRITE 2
38 #define MODE_I2C_READ 4
39 #define MODE_I2C_STOP 8
42 i2c_algo_dp_aux_transaction(struct i2c_adapter
*adapter
, int mode
,
43 uint8_t write_byte
, uint8_t *read_byte
)
45 struct i2c_algo_dp_aux_data
*algo_data
= adapter
->algo_data
;
46 uint16_t address
= algo_data
->address
;
53 /* Set up the command byte */
54 if (mode
& MODE_I2C_READ
)
55 msg
[0] = AUX_I2C_READ
<< 4;
57 msg
[0] = AUX_I2C_WRITE
<< 4;
59 if (!(mode
& MODE_I2C_STOP
))
60 msg
[0] |= AUX_I2C_MOT
<< 4;
62 msg
[1] = address
>> 8;
84 ret
= (*algo_data
->aux_ch
)(adapter
,
88 DRM_DEBUG("aux_ch failed %d\n", ret
);
91 switch (reply
[0] & AUX_I2C_REPLY_MASK
) {
92 case AUX_I2C_REPLY_ACK
:
93 if (mode
== MODE_I2C_READ
) {
94 *read_byte
= reply
[1];
96 return reply_bytes
- 1;
97 case AUX_I2C_REPLY_NACK
:
98 DRM_DEBUG("aux_ch nack\n");
100 case AUX_I2C_REPLY_DEFER
:
101 DRM_DEBUG("aux_ch defer\n");
105 DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply
[0]);
116 * Send the address. If the I2C link is running, this 'restarts'
117 * the connection with the new address, this is used for doing
118 * a write followed by a read (as needed for DDC)
121 i2c_algo_dp_aux_address(struct i2c_adapter
*adapter
, u16 address
, bool reading
)
123 struct i2c_algo_dp_aux_data
*algo_data
= adapter
->algo_data
;
124 int mode
= MODE_I2C_START
;
128 mode
|= MODE_I2C_READ
;
130 mode
|= MODE_I2C_WRITE
;
131 algo_data
->address
= address
;
132 algo_data
->running
= true;
133 ret
= i2c_algo_dp_aux_transaction(adapter
, mode
, 0, NULL
);
138 * Stop the I2C transaction. This closes out the link, sending
139 * a bare address packet with the MOT bit turned off
142 i2c_algo_dp_aux_stop(struct i2c_adapter
*adapter
, bool reading
)
144 struct i2c_algo_dp_aux_data
*algo_data
= adapter
->algo_data
;
145 int mode
= MODE_I2C_STOP
;
148 mode
|= MODE_I2C_READ
;
150 mode
|= MODE_I2C_WRITE
;
151 if (algo_data
->running
) {
152 (void) i2c_algo_dp_aux_transaction(adapter
, mode
, 0, NULL
);
153 algo_data
->running
= false;
158 * Write a single byte to the current I2C address, the
159 * the I2C link must be running or this returns -EIO
162 i2c_algo_dp_aux_put_byte(struct i2c_adapter
*adapter
, u8 byte
)
164 struct i2c_algo_dp_aux_data
*algo_data
= adapter
->algo_data
;
167 if (!algo_data
->running
)
170 ret
= i2c_algo_dp_aux_transaction(adapter
, MODE_I2C_WRITE
, byte
, NULL
);
175 * Read a single byte from the current I2C address, the
176 * I2C link must be running or this returns -EIO
179 i2c_algo_dp_aux_get_byte(struct i2c_adapter
*adapter
, u8
*byte_ret
)
181 struct i2c_algo_dp_aux_data
*algo_data
= adapter
->algo_data
;
184 if (!algo_data
->running
)
187 ret
= i2c_algo_dp_aux_transaction(adapter
, MODE_I2C_READ
, 0, byte_ret
);
192 i2c_algo_dp_aux_xfer(struct i2c_adapter
*adapter
,
193 struct i2c_msg
*msgs
,
197 bool reading
= false;
201 for (m
= 0; m
< num
; m
++) {
202 u16 len
= msgs
[m
].len
;
203 u8
*buf
= msgs
[m
].buf
;
204 reading
= (msgs
[m
].flags
& I2C_M_RD
) != 0;
205 ret
= i2c_algo_dp_aux_address(adapter
, msgs
[m
].addr
, reading
);
209 for (b
= 0; b
< len
; b
++) {
210 ret
= i2c_algo_dp_aux_get_byte(adapter
, &buf
[b
]);
215 for (b
= 0; b
< len
; b
++) {
216 ret
= i2c_algo_dp_aux_put_byte(adapter
, buf
[b
]);
226 i2c_algo_dp_aux_stop(adapter
, reading
);
227 DRM_DEBUG("dp_aux_xfer return %d\n", ret
);
232 i2c_algo_dp_aux_functionality(struct i2c_adapter
*adapter
)
234 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
|
235 I2C_FUNC_SMBUS_READ_BLOCK_DATA
|
236 I2C_FUNC_SMBUS_BLOCK_PROC_CALL
|
240 static const struct i2c_algorithm i2c_dp_aux_algo
= {
241 .master_xfer
= i2c_algo_dp_aux_xfer
,
242 .functionality
= i2c_algo_dp_aux_functionality
,
246 i2c_dp_aux_reset_bus(struct i2c_adapter
*adapter
)
248 (void) i2c_algo_dp_aux_address(adapter
, 0, false);
249 (void) i2c_algo_dp_aux_stop(adapter
, false);
254 i2c_dp_aux_prepare_bus(struct i2c_adapter
*adapter
)
256 adapter
->algo
= &i2c_dp_aux_algo
;
257 adapter
->retries
= 3;
258 i2c_dp_aux_reset_bus(adapter
);
263 i2c_dp_aux_add_bus(struct i2c_adapter
*adapter
)
267 error
= i2c_dp_aux_prepare_bus(adapter
);
270 error
= i2c_add_adapter(adapter
);
273 EXPORT_SYMBOL(i2c_dp_aux_add_bus
);