qemu/hw/display/dpcd.c
<<
>>
Prefs
   1/*
   2 * dpcd.c
   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 emulate a screen connected.
  27 */
  28
  29#include "qemu/osdep.h"
  30#include "hw/misc/aux.h"
  31#include "dpcd.h"
  32
  33/* #define DEBUG_DPCD */
  34#ifdef DEBUG_DPCD
  35#define DPRINTF(fmt, ...) do { printf("dpcd: "fmt , ## __VA_ARGS__); } while (0)
  36#else
  37#define DPRINTF(fmt, ...) do {} while (0)
  38#endif
  39
  40struct DPCDState {
  41    AUXSlave parent_obj;
  42
  43    size_t current_reg;
  44    /*
  45     * The DCPD is 0x7FFFF length but read as 0 after offset 0x600.
  46     */
  47    uint8_t dpcd_info[0x600];
  48
  49    MemoryRegion iomem;
  50};
  51
  52static void dpcd_realize(DeviceState *dev, Error **errp)
  53{
  54
  55}
  56
  57static uint64_t aux_read(void *opaque, hwaddr offset, unsigned size)
  58{
  59    uint64_t ret;
  60    DPCDState *e = DPCD(opaque);
  61    assert(size == 1);
  62
  63    if (offset <= 0x600) {
  64        ret = e->dpcd_info[offset];
  65    } else {
  66        ret = 0;
  67    }
  68
  69    DPRINTF("read %u @0x%8.8lX\n", (uint8_t)ret, offset);
  70    return ret;
  71}
  72
  73static void aux_write(void *opaque, hwaddr offset, uint64_t value,
  74                      unsigned size)
  75{
  76    DPCDState *e = DPCD(opaque);
  77    assert(size == 1);
  78
  79    DPRINTF("write %u @0x%8.8lX\n", (uint8_t)value, offset);
  80
  81    if (offset <= 0x600) {
  82        e->dpcd_info[offset] = value;
  83    }
  84}
  85
  86static const MemoryRegionOps aux_ops = {
  87    .read = aux_read,
  88    .write = aux_write
  89};
  90
  91static void aux_edid_init(Object *obj)
  92{
  93    /*
  94     * Create a default DPCD..
  95     */
  96    DPCDState *s = DPCD(obj);
  97
  98    memset(&(s->dpcd_info), 0, sizeof(s->dpcd_info));
  99
 100    s->current_reg = 0;
 101
 102    s->dpcd_info[0x00] = DPCD_REV_1_0;
 103    s->dpcd_info[0x01] = DPCD_2_7GBPS;
 104    s->dpcd_info[0x02] = 0x1;
 105    s->dpcd_info[0x08] = DPCD_EDID_PRESENT;
 106    s->dpcd_info[0x09] = 0xFF;
 107
 108    /* CR DONE, CE DONE, SYMBOL LOCKED.. */
 109    s->dpcd_info[0x202] = 0x07;
 110    /* INTERLANE_ALIGN_DONE.. */
 111    s->dpcd_info[0x204] = 0x01;
 112    s->dpcd_info[0x205] = 0x01;
 113
 114    /*
 115     * Create the address-map.
 116     */
 117    memory_region_init_io(&s->iomem, obj, &aux_ops, s, TYPE_DPCD, 0x7FFFF);
 118    aux_init_mmio(AUX_SLAVE(obj), &s->iomem);
 119}
 120
 121static void aux_edid_class_init(ObjectClass *oc, void *data)
 122{
 123    DeviceClass *dc = DEVICE_CLASS(oc);
 124    dc->realize = dpcd_realize;
 125}
 126
 127static const TypeInfo aux_edid_info = {
 128    .name          = TYPE_DPCD,
 129    .parent        = TYPE_AUX_SLAVE,
 130    .instance_size = sizeof(DPCDState),
 131    .instance_init = aux_edid_init,
 132    .class_init    = aux_edid_class_init,
 133};
 134
 135static void aux_edid_register_types(void)
 136{
 137    type_register_static(&aux_edid_info);
 138}
 139
 140type_init(aux_edid_register_types)
 141