diff mbox

[V4,4/8] introduce dpcd module.

Message ID 1437499031-11741-5-git-send-email-fred.konrad@greensocs.com
State New
Headers show

Commit Message

fred.konrad@greensocs.com July 21, 2015, 5:17 p.m. UTC
From: KONRAD Frederic <fred.konrad@greensocs.com>

This introduces a DPCD module. It wires on a aux-bus and can be accessed by
driver to get lane-speed, etc.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 default-configs/aarch64-softmmu.mak |   1 +
 hw/display/Makefile.objs            |   1 +
 hw/display/dpcd.c                   | 171 ++++++++++++++++++++++++++++++++++++
 hw/display/dpcd.h                   | 105 ++++++++++++++++++++++
 4 files changed, 278 insertions(+)
 create mode 100644 hw/display/dpcd.c
 create mode 100644 hw/display/dpcd.h

Comments

Alistair Francis Sept. 1, 2015, 11:19 p.m. UTC | #1
On Tue, Jul 21, 2015 at 10:17 AM,  <fred.konrad@greensocs.com> wrote:
> From: KONRAD Frederic <fred.konrad@greensocs.com>
>
> This introduces a DPCD module. It wires on a aux-bus and can be accessed by
> driver to get lane-speed, etc.

"the driver"

Also, the commit titles are a little messy. The capitalisation should
be consistent and there shouldn't be any full stops. These should be
fixed before being committed.
Can you fix them up when you resend the patch series?

Otherwise:

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
Tested-By: Hyun Kwon <hyun.kwon@xilinx.com>

Thanks,

Alistair


>
> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
> ---
>  default-configs/aarch64-softmmu.mak |   1 +
>  hw/display/Makefile.objs            |   1 +
>  hw/display/dpcd.c                   | 171 ++++++++++++++++++++++++++++++++++++
>  hw/display/dpcd.h                   | 105 ++++++++++++++++++++++
>  4 files changed, 278 insertions(+)
>  create mode 100644 hw/display/dpcd.c
>  create mode 100644 hw/display/dpcd.h
>
> diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
> index d3a2665..87165b7 100644
> --- a/default-configs/aarch64-softmmu.mak
> +++ b/default-configs/aarch64-softmmu.mak
> @@ -4,4 +4,5 @@
>  include arm-softmmu.mak
>
>  CONFIG_AUX=y
> +CONFIG_DPCD=y
>  CONFIG_XLNX_ZYNQMP=y
> diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
> index dd8ea76..6d7004a 100644
> --- a/hw/display/Makefile.objs
> +++ b/hw/display/Makefile.objs
> @@ -38,3 +38,4 @@ common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
>  obj-$(CONFIG_VIRTIO) += virtio-gpu.o
>  obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o
>  obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
> +obj-$(CONFIG_DPCD) += dpcd.o
> diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c
> new file mode 100644
> index 0000000..83dd489
> --- /dev/null
> +++ b/hw/display/dpcd.c
> @@ -0,0 +1,171 @@
> +/*
> + * dpcd.c
> + *
> + *  Copyright (C) 2015 : GreenSocs Ltd
> + *      http://www.greensocs.com/ , email: info@greensocs.com
> + *
> + *  Developed by :
> + *  Frederic Konrad   <fred.konrad@greensocs.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option)any later version.
> + *
> + * 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/>.
> + *
> + */
> +
> +/*
> + * This is a simple AUX slave which emulates a connected screen.
> + */
> +
> +#include "hw/aux.h"
> +#include "dpcd.h"
> +
> +#ifndef DEBUG_DPCD
> +#define DEBUG_DPCD 0
> +#endif
> +
> +#define DPRINTF(fmt, ...) do {                                                 \
> +    if (DEBUG_DPCD) {                                                          \
> +        qemu_log("dpcd: " fmt, ## __VA_ARGS__);                                \
> +    }                                                                          \
> +} while (0);
> +
> +#define DPCD_READABLE_AREA                      0x600
> +
> +struct DPCDState {
> +    /*< private >*/
> +    AUXSlave parent_obj;
> +
> +    /*< public >*/
> +    /*
> +     * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
> +     */
> +    uint8_t dpcd_info[DPCD_READABLE_AREA];
> +
> +    MemoryRegion iomem;
> +};
> +
> +static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    uint8_t ret;
> +    DPCDState *e = DPCD(opaque);
> +
> +    if (offset < DPCD_READABLE_AREA) {
> +        ret = e->dpcd_info[offset];
> +    } else {
> +        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
> +                                       offset);
> +        ret = 0;
> +    }
> +
> +    DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
> +    return ret;
> +}
> +
> +static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
> +                       unsigned size)
> +{
> +    DPCDState *e = DPCD(opaque);
> +
> +    DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);
> +
> +    if (offset < DPCD_READABLE_AREA) {
> +        e->dpcd_info[offset] = value;
> +    } else {
> +        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
> +                                       offset);
> +    }
> +}
> +
> +static const MemoryRegionOps aux_ops = {
> +    .read = dpcd_read,
> +    .write = dpcd_write,
> +    .valid = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +    .impl = {
> +        .min_access_size = 1,
> +        .max_access_size = 1,
> +    },
> +};
> +
> +static void dpcd_reset(DeviceState *dev)
> +{
> +    DPCDState *s = DPCD(dev);
> +
> +    memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
> +
> +    s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
> +    s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
> +    s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
> +    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
> +    /* buffer size */
> +    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;
> +
> +    s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
> +                                      | DPCD_LANE0_CHANNEL_EQ_DONE
> +                                      | DPCD_LANE0_SYMBOL_LOCKED
> +                                      | DPCD_LANE1_CR_DONE
> +                                      | DPCD_LANE1_CHANNEL_EQ_DONE
> +                                      | DPCD_LANE1_SYMBOL_LOCKED;
> +    s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
> +                                      | DPCD_LANE2_CHANNEL_EQ_DONE
> +                                      | DPCD_LANE2_SYMBOL_LOCKED
> +                                      | DPCD_LANE3_CR_DONE
> +                                      | DPCD_LANE3_CHANNEL_EQ_DONE
> +                                      | DPCD_LANE3_SYMBOL_LOCKED;
> +
> +    s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
> +    s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
> +}
> +
> +static void dpcd_init(Object *obj)
> +{
> +    DPCDState *s = DPCD(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
> +    aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
> +}
> +
> +static const VMStateDescription vmstate_dpcd = {
> +    .name = TYPE_DPCD,
> +    .version_id = 0,
> +    .minimum_version_id = 0,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void dpcd_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->reset = dpcd_reset;
> +    dc->vmsd = &vmstate_dpcd;
> +}
> +
> +static const TypeInfo dpcd_info = {
> +    .name          = TYPE_DPCD,
> +    .parent        = TYPE_AUX_SLAVE,
> +    .instance_size = sizeof(DPCDState),
> +    .class_init    = dpcd_class_init,
> +    .instance_init = dpcd_init,
> +};
> +
> +static void dpcd_register_types(void)
> +{
> +    type_register_static(&dpcd_info);
> +}
> +
> +type_init(dpcd_register_types)
> diff --git a/hw/display/dpcd.h b/hw/display/dpcd.h
> new file mode 100644
> index 0000000..274dc2e
> --- /dev/null
> +++ b/hw/display/dpcd.h
> @@ -0,0 +1,105 @@
> +/*
> + * dpcd.h
> + *
> + *  Copyright (C)2015 : GreenSocs Ltd
> + *      http://www.greensocs.com/ , email: info@greensocs.com
> + *
> + *  Developed by :
> + *  Frederic Konrad   <fred.konrad@greensocs.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option)any later version.
> + *
> + * 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/>.
> + *
> + */
> +
> +#ifndef DPCD_H
> +#define DPCD_H
> +
> +typedef struct DPCDState DPCDState;
> +
> +#define TYPE_DPCD "dpcd"
> +#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD)
> +
> +/* DCPD Revision. */
> +#define DPCD_REVISION                           0x00
> +#define DPCD_REV_1_0                            0x10
> +#define DPCD_REV_1_1                            0x11
> +
> +/* DCPD Max Link Rate. */
> +#define DPCD_MAX_LINK_RATE                      0x01
> +#define DPCD_1_62GBPS                           0x06
> +#define DPCD_2_7GBPS                            0x0A
> +#define DPCD_5_4GBPS                            0x14
> +
> +#define DPCD_MAX_LANE_COUNT                     0x02
> +#define DPCD_ONE_LANE                           0x01
> +#define DPCD_TWO_LANES                          0x02
> +#define DPCD_FOUR_LANES                         0x04
> +
> +/* DCPD Max down spread. */
> +#define DPCD_UP_TO_0_5                          0x01
> +#define DPCD_NO_AUX_HANDSHAKE_LINK_TRAINING     0x40
> +
> +/* DCPD Downstream port type. */
> +#define DPCD_DISPLAY_PORT                       0x00
> +#define DPCD_ANALOG                             0x02
> +#define DPCD_DVI_HDMI                           0x04
> +#define DPCD_OTHER                              0x06
> +
> +/* DPCD Format conversion. */
> +#define DPCD_FORMAT_CONVERSION                  0x08
> +
> +/* Main link channel coding. */
> +#define DPCD_ANSI_8B_10B                        0x01
> +
> +/* Down stream port count. */
> +#define DPCD_OUI_SUPPORTED                      0x80
> +
> +/* Receiver port capability. */
> +#define DPCD_RECEIVE_PORT0_CAP_0                0x08
> +#define DPCD_RECEIVE_PORT0_CAP_1                0x09
> +#define DPCD_EDID_PRESENT                       0x02
> +#define DPCD_ASSOCIATED_TO_PRECEDING_PORT       0x04
> +
> +/* Down stream port capability. */
> +#define DPCD_CAP_DISPLAY_PORT                   0x000
> +#define DPCD_CAP_ANALOG_VGA                     0x001
> +#define DPCD_CAP_DVI                            0x002
> +#define DPCD_CAP_HDMI                           0x003
> +#define DPCD_CAP_OTHER                          0x100
> +
> +#define DPCD_LANE0_1_STATUS                     0x202
> +#define DPCD_LANE0_CR_DONE                      (1 << 0)
> +#define DPCD_LANE0_CHANNEL_EQ_DONE              (1 << 1)
> +#define DPCD_LANE0_SYMBOL_LOCKED                (1 << 2)
> +#define DPCD_LANE1_CR_DONE                      (1 << 4)
> +#define DPCD_LANE1_CHANNEL_EQ_DONE              (1 << 5)
> +#define DPCD_LANE1_SYMBOL_LOCKED                (1 << 6)
> +
> +#define DPCD_LANE2_3_STATUS                     0x203
> +#define DPCD_LANE2_CR_DONE                      (1 << 0)
> +#define DPCD_LANE2_CHANNEL_EQ_DONE              (1 << 1)
> +#define DPCD_LANE2_SYMBOL_LOCKED                (1 << 2)
> +#define DPCD_LANE3_CR_DONE                      (1 << 4)
> +#define DPCD_LANE3_CHANNEL_EQ_DONE              (1 << 5)
> +#define DPCD_LANE3_SYMBOL_LOCKED                (1 << 6)
> +
> +#define DPCD_LANE_ALIGN_STATUS_UPDATED          0x204
> +#define DPCD_INTERLANE_ALIGN_DONE               0x01
> +#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED     0x40
> +#define DPCD_LINK_STATUS_UPDATED                0x80
> +
> +#define DPCD_SINK_STATUS                        0x205
> +#define DPCD_RECEIVE_PORT_0_STATUS              0x01
> +
> +#endif /* !DPCD_H */
> --
> 1.9.0
>
>
fred.konrad@greensocs.com Sept. 4, 2015, 10:54 p.m. UTC | #2
On 02/09/2015 01:19, Alistair Francis wrote:
> On Tue, Jul 21, 2015 at 10:17 AM,  <fred.konrad@greensocs.com> wrote:
>> From: KONRAD Frederic <fred.konrad@greensocs.com>
>>
>> This introduces a DPCD module. It wires on a aux-bus and can be accessed by
>> driver to get lane-speed, etc.
> "the driver"
>
> Also, the commit titles are a little messy. The capitalisation should
> be consistent and there shouldn't be any full stops. These should be
> fixed before being committed.
> Can you fix them up when you resend the patch series?

Yes ok.

Thanks,
Fred
>
> Otherwise:
>
> Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>
> Tested-By: Hyun Kwon <hyun.kwon@xilinx.com>
>
> Thanks,
>
> Alistair
>
>
>> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
>> ---
>>   default-configs/aarch64-softmmu.mak |   1 +
>>   hw/display/Makefile.objs            |   1 +
>>   hw/display/dpcd.c                   | 171 ++++++++++++++++++++++++++++++++++++
>>   hw/display/dpcd.h                   | 105 ++++++++++++++++++++++
>>   4 files changed, 278 insertions(+)
>>   create mode 100644 hw/display/dpcd.c
>>   create mode 100644 hw/display/dpcd.h
>>
>> diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
>> index d3a2665..87165b7 100644
>> --- a/default-configs/aarch64-softmmu.mak
>> +++ b/default-configs/aarch64-softmmu.mak
>> @@ -4,4 +4,5 @@
>>   include arm-softmmu.mak
>>
>>   CONFIG_AUX=y
>> +CONFIG_DPCD=y
>>   CONFIG_XLNX_ZYNQMP=y
>> diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
>> index dd8ea76..6d7004a 100644
>> --- a/hw/display/Makefile.objs
>> +++ b/hw/display/Makefile.objs
>> @@ -38,3 +38,4 @@ common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
>>   obj-$(CONFIG_VIRTIO) += virtio-gpu.o
>>   obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o
>>   obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
>> +obj-$(CONFIG_DPCD) += dpcd.o
>> diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c
>> new file mode 100644
>> index 0000000..83dd489
>> --- /dev/null
>> +++ b/hw/display/dpcd.c
>> @@ -0,0 +1,171 @@
>> +/*
>> + * dpcd.c
>> + *
>> + *  Copyright (C) 2015 : GreenSocs Ltd
>> + *      http://www.greensocs.com/ , email: info@greensocs.com
>> + *
>> + *  Developed by :
>> + *  Frederic Konrad   <fred.konrad@greensocs.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option)any later version.
>> + *
>> + * 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/>.
>> + *
>> + */
>> +
>> +/*
>> + * This is a simple AUX slave which emulates a connected screen.
>> + */
>> +
>> +#include "hw/aux.h"
>> +#include "dpcd.h"
>> +
>> +#ifndef DEBUG_DPCD
>> +#define DEBUG_DPCD 0
>> +#endif
>> +
>> +#define DPRINTF(fmt, ...) do {                                                 \
>> +    if (DEBUG_DPCD) {                                                          \
>> +        qemu_log("dpcd: " fmt, ## __VA_ARGS__);                                \
>> +    }                                                                          \
>> +} while (0);
>> +
>> +#define DPCD_READABLE_AREA                      0x600
>> +
>> +struct DPCDState {
>> +    /*< private >*/
>> +    AUXSlave parent_obj;
>> +
>> +    /*< public >*/
>> +    /*
>> +     * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
>> +     */
>> +    uint8_t dpcd_info[DPCD_READABLE_AREA];
>> +
>> +    MemoryRegion iomem;
>> +};
>> +
>> +static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
>> +{
>> +    uint8_t ret;
>> +    DPCDState *e = DPCD(opaque);
>> +
>> +    if (offset < DPCD_READABLE_AREA) {
>> +        ret = e->dpcd_info[offset];
>> +    } else {
>> +        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
>> +                                       offset);
>> +        ret = 0;
>> +    }
>> +
>> +    DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
>> +    return ret;
>> +}
>> +
>> +static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
>> +                       unsigned size)
>> +{
>> +    DPCDState *e = DPCD(opaque);
>> +
>> +    DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);
>> +
>> +    if (offset < DPCD_READABLE_AREA) {
>> +        e->dpcd_info[offset] = value;
>> +    } else {
>> +        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
>> +                                       offset);
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps aux_ops = {
>> +    .read = dpcd_read,
>> +    .write = dpcd_write,
>> +    .valid = {
>> +        .min_access_size = 1,
>> +        .max_access_size = 1,
>> +    },
>> +    .impl = {
>> +        .min_access_size = 1,
>> +        .max_access_size = 1,
>> +    },
>> +};
>> +
>> +static void dpcd_reset(DeviceState *dev)
>> +{
>> +    DPCDState *s = DPCD(dev);
>> +
>> +    memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
>> +
>> +    s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
>> +    s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
>> +    s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
>> +    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
>> +    /* buffer size */
>> +    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;
>> +
>> +    s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
>> +                                      | DPCD_LANE0_CHANNEL_EQ_DONE
>> +                                      | DPCD_LANE0_SYMBOL_LOCKED
>> +                                      | DPCD_LANE1_CR_DONE
>> +                                      | DPCD_LANE1_CHANNEL_EQ_DONE
>> +                                      | DPCD_LANE1_SYMBOL_LOCKED;
>> +    s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
>> +                                      | DPCD_LANE2_CHANNEL_EQ_DONE
>> +                                      | DPCD_LANE2_SYMBOL_LOCKED
>> +                                      | DPCD_LANE3_CR_DONE
>> +                                      | DPCD_LANE3_CHANNEL_EQ_DONE
>> +                                      | DPCD_LANE3_SYMBOL_LOCKED;
>> +
>> +    s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
>> +    s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
>> +}
>> +
>> +static void dpcd_init(Object *obj)
>> +{
>> +    DPCDState *s = DPCD(obj);
>> +
>> +    memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
>> +    aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
>> +}
>> +
>> +static const VMStateDescription vmstate_dpcd = {
>> +    .name = TYPE_DPCD,
>> +    .version_id = 0,
>> +    .minimum_version_id = 0,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>> +static void dpcd_class_init(ObjectClass *oc, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(oc);
>> +
>> +    dc->reset = dpcd_reset;
>> +    dc->vmsd = &vmstate_dpcd;
>> +}
>> +
>> +static const TypeInfo dpcd_info = {
>> +    .name          = TYPE_DPCD,
>> +    .parent        = TYPE_AUX_SLAVE,
>> +    .instance_size = sizeof(DPCDState),
>> +    .class_init    = dpcd_class_init,
>> +    .instance_init = dpcd_init,
>> +};
>> +
>> +static void dpcd_register_types(void)
>> +{
>> +    type_register_static(&dpcd_info);
>> +}
>> +
>> +type_init(dpcd_register_types)
>> diff --git a/hw/display/dpcd.h b/hw/display/dpcd.h
>> new file mode 100644
>> index 0000000..274dc2e
>> --- /dev/null
>> +++ b/hw/display/dpcd.h
>> @@ -0,0 +1,105 @@
>> +/*
>> + * dpcd.h
>> + *
>> + *  Copyright (C)2015 : GreenSocs Ltd
>> + *      http://www.greensocs.com/ , email: info@greensocs.com
>> + *
>> + *  Developed by :
>> + *  Frederic Konrad   <fred.konrad@greensocs.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation, either version 2 of the License, or
>> + * (at your option)any later version.
>> + *
>> + * 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/>.
>> + *
>> + */
>> +
>> +#ifndef DPCD_H
>> +#define DPCD_H
>> +
>> +typedef struct DPCDState DPCDState;
>> +
>> +#define TYPE_DPCD "dpcd"
>> +#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD)
>> +
>> +/* DCPD Revision. */
>> +#define DPCD_REVISION                           0x00
>> +#define DPCD_REV_1_0                            0x10
>> +#define DPCD_REV_1_1                            0x11
>> +
>> +/* DCPD Max Link Rate. */
>> +#define DPCD_MAX_LINK_RATE                      0x01
>> +#define DPCD_1_62GBPS                           0x06
>> +#define DPCD_2_7GBPS                            0x0A
>> +#define DPCD_5_4GBPS                            0x14
>> +
>> +#define DPCD_MAX_LANE_COUNT                     0x02
>> +#define DPCD_ONE_LANE                           0x01
>> +#define DPCD_TWO_LANES                          0x02
>> +#define DPCD_FOUR_LANES                         0x04
>> +
>> +/* DCPD Max down spread. */
>> +#define DPCD_UP_TO_0_5                          0x01
>> +#define DPCD_NO_AUX_HANDSHAKE_LINK_TRAINING     0x40
>> +
>> +/* DCPD Downstream port type. */
>> +#define DPCD_DISPLAY_PORT                       0x00
>> +#define DPCD_ANALOG                             0x02
>> +#define DPCD_DVI_HDMI                           0x04
>> +#define DPCD_OTHER                              0x06
>> +
>> +/* DPCD Format conversion. */
>> +#define DPCD_FORMAT_CONVERSION                  0x08
>> +
>> +/* Main link channel coding. */
>> +#define DPCD_ANSI_8B_10B                        0x01
>> +
>> +/* Down stream port count. */
>> +#define DPCD_OUI_SUPPORTED                      0x80
>> +
>> +/* Receiver port capability. */
>> +#define DPCD_RECEIVE_PORT0_CAP_0                0x08
>> +#define DPCD_RECEIVE_PORT0_CAP_1                0x09
>> +#define DPCD_EDID_PRESENT                       0x02
>> +#define DPCD_ASSOCIATED_TO_PRECEDING_PORT       0x04
>> +
>> +/* Down stream port capability. */
>> +#define DPCD_CAP_DISPLAY_PORT                   0x000
>> +#define DPCD_CAP_ANALOG_VGA                     0x001
>> +#define DPCD_CAP_DVI                            0x002
>> +#define DPCD_CAP_HDMI                           0x003
>> +#define DPCD_CAP_OTHER                          0x100
>> +
>> +#define DPCD_LANE0_1_STATUS                     0x202
>> +#define DPCD_LANE0_CR_DONE                      (1 << 0)
>> +#define DPCD_LANE0_CHANNEL_EQ_DONE              (1 << 1)
>> +#define DPCD_LANE0_SYMBOL_LOCKED                (1 << 2)
>> +#define DPCD_LANE1_CR_DONE                      (1 << 4)
>> +#define DPCD_LANE1_CHANNEL_EQ_DONE              (1 << 5)
>> +#define DPCD_LANE1_SYMBOL_LOCKED                (1 << 6)
>> +
>> +#define DPCD_LANE2_3_STATUS                     0x203
>> +#define DPCD_LANE2_CR_DONE                      (1 << 0)
>> +#define DPCD_LANE2_CHANNEL_EQ_DONE              (1 << 1)
>> +#define DPCD_LANE2_SYMBOL_LOCKED                (1 << 2)
>> +#define DPCD_LANE3_CR_DONE                      (1 << 4)
>> +#define DPCD_LANE3_CHANNEL_EQ_DONE              (1 << 5)
>> +#define DPCD_LANE3_SYMBOL_LOCKED                (1 << 6)
>> +
>> +#define DPCD_LANE_ALIGN_STATUS_UPDATED          0x204
>> +#define DPCD_INTERLANE_ALIGN_DONE               0x01
>> +#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED     0x40
>> +#define DPCD_LINK_STATUS_UPDATED                0x80
>> +
>> +#define DPCD_SINK_STATUS                        0x205
>> +#define DPCD_RECEIVE_PORT_0_STATUS              0x01
>> +
>> +#endif /* !DPCD_H */
>> --
>> 1.9.0
>>
>>
diff mbox

Patch

diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
index d3a2665..87165b7 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -4,4 +4,5 @@ 
 include arm-softmmu.mak
 
 CONFIG_AUX=y
+CONFIG_DPCD=y
 CONFIG_XLNX_ZYNQMP=y
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index dd8ea76..6d7004a 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -38,3 +38,4 @@  common-obj-$(CONFIG_QXL) += qxl.o qxl-logger.o qxl-render.o
 obj-$(CONFIG_VIRTIO) += virtio-gpu.o
 obj-$(CONFIG_VIRTIO_PCI) += virtio-gpu-pci.o
 obj-$(CONFIG_VIRTIO_VGA) += virtio-vga.o
+obj-$(CONFIG_DPCD) += dpcd.o
diff --git a/hw/display/dpcd.c b/hw/display/dpcd.c
new file mode 100644
index 0000000..83dd489
--- /dev/null
+++ b/hw/display/dpcd.c
@@ -0,0 +1,171 @@ 
+/*
+ * dpcd.c
+ *
+ *  Copyright (C) 2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option)any later version.
+ *
+ * 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/>.
+ *
+ */
+
+/*
+ * This is a simple AUX slave which emulates a connected screen.
+ */
+
+#include "hw/aux.h"
+#include "dpcd.h"
+
+#ifndef DEBUG_DPCD
+#define DEBUG_DPCD 0
+#endif
+
+#define DPRINTF(fmt, ...) do {                                                 \
+    if (DEBUG_DPCD) {                                                          \
+        qemu_log("dpcd: " fmt, ## __VA_ARGS__);                                \
+    }                                                                          \
+} while (0);
+
+#define DPCD_READABLE_AREA                      0x600
+
+struct DPCDState {
+    /*< private >*/
+    AUXSlave parent_obj;
+
+    /*< public >*/
+    /*
+     * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
+     */
+    uint8_t dpcd_info[DPCD_READABLE_AREA];
+
+    MemoryRegion iomem;
+};
+
+static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
+{
+    uint8_t ret;
+    DPCDState *e = DPCD(opaque);
+
+    if (offset < DPCD_READABLE_AREA) {
+        ret = e->dpcd_info[offset];
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
+                                       offset);
+        ret = 0;
+    }
+
+    DPRINTF("read 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", ret, offset);
+    return ret;
+}
+
+static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
+                       unsigned size)
+{
+    DPCDState *e = DPCD(opaque);
+
+    DPRINTF("write 0x%" PRIX8 " @0x%" HWADDR_PRIX "\n", (uint8_t)value, offset);
+
+    if (offset < DPCD_READABLE_AREA) {
+        e->dpcd_info[offset] = value;
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
+                                       offset);
+    }
+}
+
+static const MemoryRegionOps aux_ops = {
+    .read = dpcd_read,
+    .write = dpcd_write,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 1,
+    },
+};
+
+static void dpcd_reset(DeviceState *dev)
+{
+    DPCDState *s = DPCD(dev);
+
+    memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
+
+    s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
+    s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
+    s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
+    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
+    /* buffer size */
+    s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;
+
+    s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
+                                      | DPCD_LANE0_CHANNEL_EQ_DONE
+                                      | DPCD_LANE0_SYMBOL_LOCKED
+                                      | DPCD_LANE1_CR_DONE
+                                      | DPCD_LANE1_CHANNEL_EQ_DONE
+                                      | DPCD_LANE1_SYMBOL_LOCKED;
+    s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
+                                      | DPCD_LANE2_CHANNEL_EQ_DONE
+                                      | DPCD_LANE2_SYMBOL_LOCKED
+                                      | DPCD_LANE3_CR_DONE
+                                      | DPCD_LANE3_CHANNEL_EQ_DONE
+                                      | DPCD_LANE3_SYMBOL_LOCKED;
+
+    s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
+    s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
+}
+
+static void dpcd_init(Object *obj)
+{
+    DPCDState *s = DPCD(obj);
+
+    memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
+    aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
+}
+
+static const VMStateDescription vmstate_dpcd = {
+    .name = TYPE_DPCD,
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void dpcd_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->reset = dpcd_reset;
+    dc->vmsd = &vmstate_dpcd;
+}
+
+static const TypeInfo dpcd_info = {
+    .name          = TYPE_DPCD,
+    .parent        = TYPE_AUX_SLAVE,
+    .instance_size = sizeof(DPCDState),
+    .class_init    = dpcd_class_init,
+    .instance_init = dpcd_init,
+};
+
+static void dpcd_register_types(void)
+{
+    type_register_static(&dpcd_info);
+}
+
+type_init(dpcd_register_types)
diff --git a/hw/display/dpcd.h b/hw/display/dpcd.h
new file mode 100644
index 0000000..274dc2e
--- /dev/null
+++ b/hw/display/dpcd.h
@@ -0,0 +1,105 @@ 
+/*
+ * dpcd.h
+ *
+ *  Copyright (C)2015 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option)any later version.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef DPCD_H
+#define DPCD_H
+
+typedef struct DPCDState DPCDState;
+
+#define TYPE_DPCD "dpcd"
+#define DPCD(obj) OBJECT_CHECK(DPCDState, (obj), TYPE_DPCD)
+
+/* DCPD Revision. */
+#define DPCD_REVISION                           0x00
+#define DPCD_REV_1_0                            0x10
+#define DPCD_REV_1_1                            0x11
+
+/* DCPD Max Link Rate. */
+#define DPCD_MAX_LINK_RATE                      0x01
+#define DPCD_1_62GBPS                           0x06
+#define DPCD_2_7GBPS                            0x0A
+#define DPCD_5_4GBPS                            0x14
+
+#define DPCD_MAX_LANE_COUNT                     0x02
+#define DPCD_ONE_LANE                           0x01
+#define DPCD_TWO_LANES                          0x02
+#define DPCD_FOUR_LANES                         0x04
+
+/* DCPD Max down spread. */
+#define DPCD_UP_TO_0_5                          0x01
+#define DPCD_NO_AUX_HANDSHAKE_LINK_TRAINING     0x40
+
+/* DCPD Downstream port type. */
+#define DPCD_DISPLAY_PORT                       0x00
+#define DPCD_ANALOG                             0x02
+#define DPCD_DVI_HDMI                           0x04
+#define DPCD_OTHER                              0x06
+
+/* DPCD Format conversion. */
+#define DPCD_FORMAT_CONVERSION                  0x08
+
+/* Main link channel coding. */
+#define DPCD_ANSI_8B_10B                        0x01
+
+/* Down stream port count. */
+#define DPCD_OUI_SUPPORTED                      0x80
+
+/* Receiver port capability. */
+#define DPCD_RECEIVE_PORT0_CAP_0                0x08
+#define DPCD_RECEIVE_PORT0_CAP_1                0x09
+#define DPCD_EDID_PRESENT                       0x02
+#define DPCD_ASSOCIATED_TO_PRECEDING_PORT       0x04
+
+/* Down stream port capability. */
+#define DPCD_CAP_DISPLAY_PORT                   0x000
+#define DPCD_CAP_ANALOG_VGA                     0x001
+#define DPCD_CAP_DVI                            0x002
+#define DPCD_CAP_HDMI                           0x003
+#define DPCD_CAP_OTHER                          0x100
+
+#define DPCD_LANE0_1_STATUS                     0x202
+#define DPCD_LANE0_CR_DONE                      (1 << 0)
+#define DPCD_LANE0_CHANNEL_EQ_DONE              (1 << 1)
+#define DPCD_LANE0_SYMBOL_LOCKED                (1 << 2)
+#define DPCD_LANE1_CR_DONE                      (1 << 4)
+#define DPCD_LANE1_CHANNEL_EQ_DONE              (1 << 5)
+#define DPCD_LANE1_SYMBOL_LOCKED                (1 << 6)
+
+#define DPCD_LANE2_3_STATUS                     0x203
+#define DPCD_LANE2_CR_DONE                      (1 << 0)
+#define DPCD_LANE2_CHANNEL_EQ_DONE              (1 << 1)
+#define DPCD_LANE2_SYMBOL_LOCKED                (1 << 2)
+#define DPCD_LANE3_CR_DONE                      (1 << 4)
+#define DPCD_LANE3_CHANNEL_EQ_DONE              (1 << 5)
+#define DPCD_LANE3_SYMBOL_LOCKED                (1 << 6)
+
+#define DPCD_LANE_ALIGN_STATUS_UPDATED          0x204
+#define DPCD_INTERLANE_ALIGN_DONE               0x01
+#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED     0x40
+#define DPCD_LINK_STATUS_UPDATED                0x80
+
+#define DPCD_SINK_STATUS                        0x205
+#define DPCD_RECEIVE_PORT_0_STATUS              0x01
+
+#endif /* !DPCD_H */