qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

dpcd.c (4788B)


      1 /*
      2  * Xilinx Display Port Control Data
      3  *
      4  *  Copyright (C) 2015 : GreenSocs Ltd
      5  *      http://www.greensocs.com/ , email: info@greensocs.com
      6  *
      7  *  Developed by :
      8  *  Frederic Konrad   <fred.konrad@greensocs.com>
      9  *
     10  * This program is free software; you can redistribute it and/or modify
     11  * it under the terms of the GNU General Public License as published by
     12  * the Free Software Foundation, either version 2 of the License, or
     13  * (at your option)any later version.
     14  *
     15  * This program is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18  * GNU General Public License for more details.
     19  *
     20  * You should have received a copy of the GNU General Public License along
     21  * with this program; if not, see <http://www.gnu.org/licenses/>.
     22  *
     23  */
     24 
     25 /*
     26  * This is a simple AUX slave which emulates a connected screen.
     27  */
     28 
     29 #include "qemu/osdep.h"
     30 #include "qemu/log.h"
     31 #include "qemu/module.h"
     32 #include "hw/misc/auxbus.h"
     33 #include "migration/vmstate.h"
     34 #include "hw/display/dpcd.h"
     35 #include "trace.h"
     36 
     37 #define DPCD_READABLE_AREA                      0x600
     38 
     39 struct DPCDState {
     40     /*< private >*/
     41     AUXSlave parent_obj;
     42 
     43     /*< public >*/
     44     /*
     45      * The DCPD is 0x7FFFF length but read as 0 after offset 0x5FF.
     46      */
     47     uint8_t dpcd_info[DPCD_READABLE_AREA];
     48 
     49     MemoryRegion iomem;
     50 };
     51 
     52 static uint64_t dpcd_read(void *opaque, hwaddr offset, unsigned size)
     53 {
     54     uint8_t ret;
     55     DPCDState *e = DPCD(opaque);
     56 
     57     if (offset < DPCD_READABLE_AREA) {
     58         ret = e->dpcd_info[offset];
     59     } else {
     60         qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
     61                                        offset);
     62         ret = 0;
     63     }
     64     trace_dpcd_read(offset, ret);
     65 
     66     return ret;
     67 }
     68 
     69 static void dpcd_write(void *opaque, hwaddr offset, uint64_t value,
     70                        unsigned size)
     71 {
     72     DPCDState *e = DPCD(opaque);
     73 
     74     trace_dpcd_write(offset, value);
     75     if (offset < DPCD_READABLE_AREA) {
     76         e->dpcd_info[offset] = value;
     77     } else {
     78         qemu_log_mask(LOG_GUEST_ERROR, "dpcd: Bad offset 0x%" HWADDR_PRIX "\n",
     79                                        offset);
     80     }
     81 }
     82 
     83 static const MemoryRegionOps aux_ops = {
     84     .read = dpcd_read,
     85     .write = dpcd_write,
     86     .valid = {
     87         .min_access_size = 1,
     88         .max_access_size = 1,
     89     },
     90     .impl = {
     91         .min_access_size = 1,
     92         .max_access_size = 1,
     93     },
     94 };
     95 
     96 static void dpcd_reset(DeviceState *dev)
     97 {
     98     DPCDState *s = DPCD(dev);
     99 
    100     memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
    101 
    102     s->dpcd_info[DPCD_REVISION] = DPCD_REV_1_0;
    103     s->dpcd_info[DPCD_MAX_LINK_RATE] = DPCD_5_4GBPS;
    104     s->dpcd_info[DPCD_MAX_LANE_COUNT] = DPCD_FOUR_LANES;
    105     s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_0] = DPCD_EDID_PRESENT;
    106     /* buffer size */
    107     s->dpcd_info[DPCD_RECEIVE_PORT0_CAP_1] = 0xFF;
    108 
    109     s->dpcd_info[DPCD_LANE0_1_STATUS] = DPCD_LANE0_CR_DONE
    110                                       | DPCD_LANE0_CHANNEL_EQ_DONE
    111                                       | DPCD_LANE0_SYMBOL_LOCKED
    112                                       | DPCD_LANE1_CR_DONE
    113                                       | DPCD_LANE1_CHANNEL_EQ_DONE
    114                                       | DPCD_LANE1_SYMBOL_LOCKED;
    115     s->dpcd_info[DPCD_LANE2_3_STATUS] = DPCD_LANE2_CR_DONE
    116                                       | DPCD_LANE2_CHANNEL_EQ_DONE
    117                                       | DPCD_LANE2_SYMBOL_LOCKED
    118                                       | DPCD_LANE3_CR_DONE
    119                                       | DPCD_LANE3_CHANNEL_EQ_DONE
    120                                       | DPCD_LANE3_SYMBOL_LOCKED;
    121 
    122     s->dpcd_info[DPCD_LANE_ALIGN_STATUS_UPDATED] = DPCD_INTERLANE_ALIGN_DONE;
    123     s->dpcd_info[DPCD_SINK_STATUS] = DPCD_RECEIVE_PORT_0_STATUS;
    124 }
    125 
    126 static void dpcd_init(Object *obj)
    127 {
    128     DPCDState *s = DPCD(obj);
    129 
    130     memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x80000);
    131     aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
    132 }
    133 
    134 static const VMStateDescription vmstate_dpcd = {
    135     .name = TYPE_DPCD,
    136     .version_id = 0,
    137     .minimum_version_id = 0,
    138     .fields = (VMStateField[]) {
    139         VMSTATE_UINT8_ARRAY_V(dpcd_info, DPCDState, DPCD_READABLE_AREA, 0),
    140         VMSTATE_END_OF_LIST()
    141     }
    142 };
    143 
    144 static void dpcd_class_init(ObjectClass *oc, void *data)
    145 {
    146     DeviceClass *dc = DEVICE_CLASS(oc);
    147 
    148     dc->reset = dpcd_reset;
    149     dc->vmsd = &vmstate_dpcd;
    150 }
    151 
    152 static const TypeInfo dpcd_info = {
    153     .name          = TYPE_DPCD,
    154     .parent        = TYPE_AUX_SLAVE,
    155     .instance_size = sizeof(DPCDState),
    156     .class_init    = dpcd_class_init,
    157     .instance_init = dpcd_init,
    158 };
    159 
    160 static void dpcd_register_types(void)
    161 {
    162     type_register_static(&dpcd_info);
    163 }
    164 
    165 type_init(dpcd_register_types)