qemu-e2k/hw/i2c/i2c-ddc.c
Corey Minyard 2ac4c5f4d2 i2c: have I2C receive operation return uint8_t
It is never supposed to fail and cannot return an error, so just
have it return the proper type.  Have it return 0xff on nothing
available, since that's what would happen on a real bus.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
2019-02-27 21:06:08 -06:00

128 lines
3.2 KiB
C

/* A simple I2C slave for returning monitor EDID data via DDC.
*
* Copyright (c) 2011 Linaro Limited
* Written by Peter Maydell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/log.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/i2c-ddc.h"
#ifndef DEBUG_I2CDDC
#define DEBUG_I2CDDC 0
#endif
#define DPRINTF(fmt, ...) do { \
if (DEBUG_I2CDDC) { \
qemu_log("i2c-ddc: " fmt , ## __VA_ARGS__); \
} \
} while (0)
static void i2c_ddc_reset(DeviceState *ds)
{
I2CDDCState *s = I2CDDC(ds);
s->firstbyte = false;
s->reg = 0;
}
static int i2c_ddc_event(I2CSlave *i2c, enum i2c_event event)
{
I2CDDCState *s = I2CDDC(i2c);
if (event == I2C_START_SEND) {
s->firstbyte = true;
}
return 0;
}
static uint8_t i2c_ddc_rx(I2CSlave *i2c)
{
I2CDDCState *s = I2CDDC(i2c);
int value;
value = s->edid_blob[s->reg % sizeof(s->edid_blob)];
s->reg++;
return value;
}
static int i2c_ddc_tx(I2CSlave *i2c, uint8_t data)
{
I2CDDCState *s = I2CDDC(i2c);
if (s->firstbyte) {
s->reg = data;
s->firstbyte = false;
DPRINTF("[EDID] Written new pointer: %u\n", data);
return 0;
}
/* Ignore all writes */
s->reg++;
return 0;
}
static void i2c_ddc_init(Object *obj)
{
I2CDDCState *s = I2CDDC(obj);
qemu_edid_generate(s->edid_blob, sizeof(s->edid_blob), &s->edid_info);
}
static const VMStateDescription vmstate_i2c_ddc = {
.name = TYPE_I2CDDC,
.version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_BOOL(firstbyte, I2CDDCState),
VMSTATE_UINT8(reg, I2CDDCState),
VMSTATE_END_OF_LIST()
}
};
static Property i2c_ddc_properties[] = {
DEFINE_EDID_PROPERTIES(I2CDDCState, edid_info),
DEFINE_PROP_END_OF_LIST(),
};
static void i2c_ddc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
dc->reset = i2c_ddc_reset;
dc->vmsd = &vmstate_i2c_ddc;
dc->props = i2c_ddc_properties;
isc->event = i2c_ddc_event;
isc->recv = i2c_ddc_rx;
isc->send = i2c_ddc_tx;
}
static TypeInfo i2c_ddc_info = {
.name = TYPE_I2CDDC,
.parent = TYPE_I2C_SLAVE,
.instance_size = sizeof(I2CDDCState),
.instance_init = i2c_ddc_init,
.class_init = i2c_ddc_class_init
};
static void ddc_register_devices(void)
{
type_register_static(&i2c_ddc_info);
}
type_init(ddc_register_devices);